diff --git a/dbrepo-metadata-service/README.md b/dbrepo-metadata-service/README.md
index 54443a4e20a8a7d2e34af4bb7bdada7833b11149..e550dc8d6b1f919d5764b25b435b4d8a2c436dd7 100644
--- a/dbrepo-metadata-service/README.md
+++ b/dbrepo-metadata-service/README.md
@@ -1,15 +1,40 @@
 # Semantics Service
 
-## Actuator
+## Test
 
-- Actuator Info: http://localhost:9099/actuator/info
-- Actuator Health: http://localhost:9099/actuator/health
-- Actuator Prometheus: http://localhost:9099/actuator/prometheus
+Run all unit and integration tests and create an HTML+TXT coverage report located in the `report` module:
 
-## Swagger UI Endpoints
+```bash
+mvn -pl rest-service clean test verify
+```
+
+Or run only unit tests 
+in [`KeycloakGatewayUnitTest.java`](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/blob/master/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/BrokerServiceGatewayTest.java):
+
+```bash
+mvn -pl rest-service -Dtest="KeycloakGatewayUnitTest" clean test
+```
+
+## Run
+
+Start the Metadata Database before and then run the Metadata Service:
+
+```bash
+mvn -pl rest-service clean spring-boot:run -Dspring-boot.run.profiles=local
+```
+
+### Endpoints
+
+#### Actuator
+
+- Info: http://localhost:9099/actuator/info
+- Health: http://localhost:9099/actuator/health
+- Prometheus: http://localhost:9099/actuator/prometheus
+
+#### Swagger UI
 
 - Swagger UI: http://localhost:9099/swagger-ui/index.html
 
-## OpenAPI Endpoints
+#### OpenAPI
 
 - OpenAPI v3 as .yaml: http://localhost:9099/v3/api-docs.yaml
\ No newline at end of file
diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java
index 72f666fdd05b3cbb1f877628db19f5a07ab59a2c..f4560c5a21f823f47dd1f68e761d1615ba12ae44 100644
--- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java
+++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java
@@ -16,6 +16,7 @@ import org.springframework.data.annotation.Id;
 import org.springframework.data.elasticsearch.annotations.Field;
 import org.springframework.data.elasticsearch.annotations.FieldType;
 
+import java.math.BigInteger;
 import java.time.Instant;
 import java.util.List;
 import java.util.UUID;
@@ -98,6 +99,26 @@ public class TableDto {
     @Field(name = "is_public", type = FieldType.Boolean)
     private Boolean isPublic;
 
+    @JsonProperty("num_rows")
+    @Schema(example = "5")
+    @Field(name = "num_rows", type = FieldType.Long)
+    private Long numRows;
+
+    @JsonProperty("data_length")
+    @Schema(example = "16384", description = "in bytes")
+    @Field(name = "data_length", type = FieldType.Long)
+    private Long dataLength;
+
+    @JsonProperty("max_data_length")
+    @Schema(example = "0", description = "in bytes")
+    @Field(name = "max_data_length", type = FieldType.Long)
+    private Long maxDataLength;
+
+    @JsonProperty("avg_row_length")
+    @Schema(example = "3276", description = "in bytes")
+    @Field(name = "avg_row_length", type = FieldType.Long)
+    private Long avgRowLength;
+
     @NotNull
     @Schema(example = "2021-03-12T15:26:21Z")
     @Field(name = "created", type = FieldType.Date)
diff --git a/dbrepo-metadata-service/pom.xml b/dbrepo-metadata-service/pom.xml
index 325514d848603f3984aeab03d7a5a3d784d5a5f5..49de9e8df13110401f3fe4c3e459d4caa9748e99 100644
--- a/dbrepo-metadata-service/pom.xml
+++ b/dbrepo-metadata-service/pom.xml
@@ -376,6 +376,7 @@
                         <exclude>at/tuwien/utils/**/*</exclude>
                         <exclude>at/tuwien/config/**/*</exclude>
                         <exclude>at/tuwien/auth/**/*</exclude>
+                        <exclude>at/tuwien/gateway/impl/ApiTemplateInterceptorImpl.class</exclude>
                         <exclude>**/testcontainers.properties</exclude>
                         <exclude>**/HibernateConnector.class</exclude>
                         <exclude>**/DbrepoMetadataServiceApplication.class</exclude>
diff --git a/dbrepo-metadata-service/report/pom.xml b/dbrepo-metadata-service/report/pom.xml
index 16300d9c59deda00d3994fd02d0eb745b7d4340b..5720cb7752707a5051f5d9ed76a104dd2b117148 100644
--- a/dbrepo-metadata-service/report/pom.xml
+++ b/dbrepo-metadata-service/report/pom.xml
@@ -19,6 +19,11 @@
             <artifactId>dbrepo-metadata-service-rest-service</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>at.tuwien</groupId>
+            <artifactId>dbrepo-metadata-service-services</artifactId>
+            <version>${project.version}</version>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/DatabaseMapper.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/DatabaseMapper.java
index f814b535176456bb0bd8e154f0a4f7ffe92ebdc9..7bd1c5d0eb55eb4aa815d9662732d9547f38aef4 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/DatabaseMapper.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/DatabaseMapper.java
@@ -117,7 +117,7 @@ public interface DatabaseMapper {
     default PreparedStatement databaseToDatabaseMetadata(Connection connection, Database database) throws QueryMalformedException {
         final StringBuilder statement = new StringBuilder("SELECT t.`TABLE_NAME`, t.`TABLE_TYPE`, t.`TABLE_ROWS`, t.`AVG_ROW_LENGTH`, t.`DATA_LENGTH`, t.`MAX_DATA_LENGTH`, COALESCE(t.`CREATE_TIME`, NOW()) as `CREATE_TIME`, t.`UPDATE_TIME`, v.`VIEW_DEFINITION` FROM information_schema.TABLES t LEFT JOIN information_schema.VIEWS v ON t.`TABLE_NAME` = v.`TABLE_NAME` WHERE t.`TABLE_SCHEMA` = '")
                 .append(database.getInternalName())
-                .append("' AND t.`TABLE_TYPE` IN ('BASE TABLE', 'SYSTEM VERSIONED', 'VIEW') AND t.`TABLE_NAME` NOT IN ('qs_queries', '_tmp') AND t.`TABLE_NAME` NOT LIKE 'hs_%'");
+                .append("' AND t.`TABLE_TYPE` IN ('BASE TABLE', 'SYSTEM VERSIONED', 'VIEW') AND t.`TABLE_NAME` NOT IN ('qs_queries', '_tmp') AND t.`TABLE_NAME` NOT LIKE 'hs_%' AND t.`TABLE_NAME` NOT LIKE '%_temporary'");
         log.trace("statement={}", statement);
         try {
             return connection.prepareStatement(statement.toString());
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/QueryMapper.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/QueryMapper.java
index 4c232eafcee6be72b107c9b315ccae9203e69a84..e45ce93aaae7cd8bb8b69a53af76edc8247a3e23 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/QueryMapper.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/QueryMapper.java
@@ -935,15 +935,6 @@ public interface QueryMapper {
         }
     }
 
-    default String selectItemToEscapedString(SelectItem data) {
-        final String item = data.toString();
-        final int idx = item.indexOf('.');
-        if (idx == -1) {
-            return "`" + item + "`";
-        }
-        return "`" + item.substring(idx + 1) + "`";
-    }
-
     default String generateInsertFromTemporaryTableSQL(Table table) {
         final StringBuilder statement = new StringBuilder("INSERT INTO `")
                 .append(table.getDatabase().getInternalName())
diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ExportEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ExportEndpoint.java
index 666b81b3935952e297412817ae7d6f8f9d22777f..5a994cdae9f2afd193aa3e42318144e068a86587 100644
--- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ExportEndpoint.java
+++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ExportEndpoint.java
@@ -68,6 +68,11 @@ public class ExportEndpoint {
                     content = {@Content(
                             mediaType = "application/json",
                             schema = @Schema(implementation = ApiErrorDto.class))}),
+            @ApiResponse(responseCode = "409",
+                    description = "Failed to export file from sidecar",
+                    content = {@Content(
+                            mediaType = "application/json",
+                            schema = @Schema(implementation = ApiErrorDto.class))}),
             @ApiResponse(responseCode = "410",
                     description = "Blob storage operation could not be completed",
                     content = {@Content(
@@ -88,9 +93,8 @@ public class ExportEndpoint {
                                                       @NotNull @PathVariable("tableId") Long tableId,
                                                       @RequestParam(required = false) Instant timestamp,
                                                       Principal principal)
-            throws TableNotFoundException, DatabaseConnectionException, TableMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, PaginationException, FileStorageException,
-            QueryMalformedException, UserNotFoundException, NotAllowedException, DataDbSidecarException {
+            throws TableNotFoundException, DatabaseNotFoundException, FileStorageException, QueryMalformedException,
+            NotAllowedException, DataDbSidecarException, DataProcessingException {
         log.debug("endpoint export table, id={}, tableId={}, timestamp={}, {}", databaseId, tableId, timestamp, PrincipalUtil.formatForDebug(principal));
         final Database database = databaseService.find(databaseId);
         if (!database.getIsPublic()) {
diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/PersistenceEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/PersistenceEndpoint.java
index a8d46160496c2144e3a92544ffcfed95af0eb7dc..a39ecc85a5c7425432519b921551dce6ff17f157 100644
--- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/PersistenceEndpoint.java
+++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/PersistenceEndpoint.java
@@ -102,7 +102,7 @@ public class PersistenceEndpoint {
                                   @NotNull Principal principal) throws IdentifierNotFoundException,
             QueryNotFoundException, IdentifierRequestException, UserNotFoundException, QueryStoreException,
             TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
-            ImageNotSupportedException, FileStorageException, DataDbSidecarException {
+            ImageNotSupportedException, FileStorageException, DataDbSidecarException, DataProcessingException {
         log.debug("endpoint find identifier, pid={}, accept={}", pid, accept);
         final Identifier identifier = identifierService.find(pid);
         log.info("Found persistent identifier with id {}", identifier.getId());
diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/QueryEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/QueryEndpoint.java
index 0b1c053865683fc0a2ed78cf896c792ea6d2530f..bcbcab6a3864280f68c5fe3bbc54adb07b5e4000 100644
--- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/QueryEndpoint.java
+++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/QueryEndpoint.java
@@ -268,7 +268,7 @@ public class QueryEndpoint {
                                     @RequestHeader(HttpHeaders.ACCEPT) String accept,
                                     Principal principal)
             throws QueryStoreException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
-            FileStorageException, QueryMalformedException, NotAllowedException, DataDbSidecarException {
+            FileStorageException, QueryMalformedException, NotAllowedException, DataDbSidecarException, DataProcessingException {
         log.debug("endpoint export query, databaseId={}, queryId={}, accept={}, {}", databaseId, queryId, accept, PrincipalUtil.formatForDebug(principal));
         final Database database = databaseService.find(databaseId);
         if (!database.getIsPublic()) {
diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableDataEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableDataEndpoint.java
index 0b1f25f0fe4dc5e105a4e3626dd186471a507cb6..d71a97293cf3bdace25a0c2fd28ea0e34f9196b8 100644
--- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableDataEndpoint.java
+++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableDataEndpoint.java
@@ -152,6 +152,11 @@ public class TableDataEndpoint {
                     content = {@Content(
                             mediaType = "application/json",
                             schema = @Schema(implementation = ApiErrorDto.class))}),
+            @ApiResponse(responseCode = "409",
+                    description = "Import failed in sidecar",
+                    content = {@Content(
+                            mediaType = "application/json",
+                            schema = @Schema(implementation = ApiErrorDto.class))}),
             @ApiResponse(responseCode = "422",
                     description = "Could not import csv via sidecar",
                     content = {@Content(
@@ -163,7 +168,7 @@ public class TableDataEndpoint {
                                           @NotNull @Valid @RequestBody ImportDto data,
                                           @NotNull Principal principal)
             throws TableNotFoundException, DatabaseNotFoundException, TableMalformedException,
-            NotAllowedException, AccessDeniedException, DataDbSidecarException {
+            NotAllowedException, AccessDeniedException, DataDbSidecarException, DataProcessingException {
         log.debug("endpoint insert data from csv, databaseId={}, tableId={}, data={}, {}", databaseId, tableId, data, PrincipalUtil.formatForDebug(principal));
         /* check */
         endpointValidator.validateOnlyWriteOwnOrWriteAllAccess(databaseId, tableId, principal);
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ExportEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ExportEndpointUnitTest.java
index 53a91d996ed9be62ffd8a7055b8375388e42a726..c31415cb42b037cd1aaf51f9544232a6e2d403ea 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ExportEndpointUnitTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ExportEndpointUnitTest.java
@@ -5,7 +5,6 @@ import at.tuwien.ExportResource;
 import at.tuwien.annotations.MockAmqp;
 import at.tuwien.annotations.MockOpensearch;
 import at.tuwien.entities.database.Database;
-import at.tuwien.entities.database.DatabaseAccess;
 import at.tuwien.exception.*;
 import at.tuwien.service.DatabaseService;
 import at.tuwien.service.QueryService;
@@ -28,7 +27,6 @@ import java.io.IOException;
 import java.security.Principal;
 import java.time.Instant;
 import java.time.temporal.ChronoUnit;
-import java.util.UUID;
 
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.Mockito.when;
@@ -55,28 +53,28 @@ public class ExportEndpointUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(NotAllowedException.class, () -> {
-            export_generic(DATABASE_1_ID, TABLE_1_ID, DATABASE_1, null, null, null, null);
+            export_generic(DATABASE_1_ID, TABLE_1_ID, DATABASE_1, null, null);
         });
     }
 
     @Test
     @WithMockUser(username = USER_1_USERNAME, authorities = {"export-table-data"})
-    public void export_publicHasRoleNoAccess_succeeds() throws TableNotFoundException, DatabaseConnectionException,
-            TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
-            PaginationException, NotAllowedException, QueryMalformedException, UserNotFoundException, IOException {
+    public void export_publicHasRoleNoAccess_succeeds() throws TableNotFoundException, NotAllowedException,
+            QueryMalformedException, DatabaseNotFoundException, IOException, FileStorageException,
+            DataProcessingException {
 
         /* test */
-        export_generic(DATABASE_1_ID, TABLE_1_ID, DATABASE_1, null, USER_1_PRINCIPAL, USER_1_ID, null);
+        export_generic(DATABASE_1_ID, TABLE_1_ID, DATABASE_1, null, USER_1_PRINCIPAL);
     }
 
     @Test
     @WithMockUser(username = USER_1_USERNAME, authorities = {"export-table-data"})
-    public void export_publicHasRoleReadAccess_succeeds() throws TableNotFoundException, DatabaseConnectionException,
-            TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
-            PaginationException, NotAllowedException, QueryMalformedException, UserNotFoundException, IOException {
+    public void export_publicHasRoleReadAccess_succeeds() throws TableNotFoundException, NotAllowedException,
+            QueryMalformedException, DatabaseNotFoundException, IOException, FileStorageException,
+            DataProcessingException {
 
         /* test */
-        export_generic(DATABASE_1_ID, TABLE_1_ID, DATABASE_1, null, USER_1_PRINCIPAL, USER_1_ID, DATABASE_1_USER_1_READ_ACCESS);
+        export_generic(DATABASE_1_ID, TABLE_1_ID, DATABASE_1, null, USER_1_PRINCIPAL);
     }
 
     @Test
@@ -86,7 +84,7 @@ public class ExportEndpointUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(NotAllowedException.class, () -> {
-            export_generic(DATABASE_1_ID, TABLE_1_ID, DATABASE_1, timestamp, null, null, null);
+            export_generic(DATABASE_1_ID, TABLE_1_ID, DATABASE_1, timestamp, null);
         });
     }
 
@@ -96,7 +94,7 @@ public class ExportEndpointUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(NotAllowedException.class, () -> {
-            export_generic(DATABASE_1_ID, TABLE_1_ID, DATABASE_1, timestamp, null, null, null);
+            export_generic(DATABASE_1_ID, TABLE_1_ID, DATABASE_1, timestamp, null);
         });
     }
 
@@ -110,50 +108,50 @@ public class ExportEndpointUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(NotAllowedException.class, () -> {
-            export_generic(DATABASE_2_ID, TABLE_1_ID, DATABASE_2, null, null, null, null);
+            export_generic(DATABASE_2_ID, TABLE_1_ID, DATABASE_2, null, null);
         });
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"export-table-data"})
-    public void export_privateHasRoleNoAccess_fails() throws TableNotFoundException, DatabaseConnectionException,
-            TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
-            PaginationException, NotAllowedException, QueryMalformedException, UserNotFoundException, IOException {
+    public void export_privateHasRoleNoAccess_fails() throws TableNotFoundException, NotAllowedException,
+            QueryMalformedException, DatabaseNotFoundException, IOException, FileStorageException,
+            DataProcessingException {
 
         /* test */
-        export_generic(DATABASE_2_ID, TABLE_1_ID, DATABASE_2, null, USER_2_PRINCIPAL, USER_2_ID, null);
+        export_generic(DATABASE_2_ID, TABLE_1_ID, DATABASE_2, null, USER_2_PRINCIPAL);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"export-table-data"})
-    public void export_HasRoleReadAccess_succeeds() throws TableNotFoundException, DatabaseConnectionException,
-            TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
-            PaginationException, NotAllowedException, QueryMalformedException, UserNotFoundException, IOException {
+    public void export_HasRoleReadAccess_succeeds() throws TableNotFoundException, NotAllowedException,
+            QueryMalformedException, DatabaseNotFoundException, IOException, FileStorageException,
+            DataProcessingException {
 
         /* test */
-        export_generic(DATABASE_2_ID, TABLE_1_ID, DATABASE_2, null, USER_2_PRINCIPAL, USER_2_ID, DATABASE_2_USER_1_WRITE_OWN_ACCESS);
+        export_generic(DATABASE_2_ID, TABLE_1_ID, DATABASE_2, null, USER_2_PRINCIPAL);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"export-table-data"})
-    public void export_privateReadWithTimestamp_succeeds() throws TableNotFoundException, DatabaseConnectionException,
-            TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
-            PaginationException, NotAllowedException, QueryMalformedException, UserNotFoundException, IOException {
+    public void export_privateReadWithTimestamp_succeeds() throws TableNotFoundException, NotAllowedException,
+            QueryMalformedException, DatabaseNotFoundException, IOException, FileStorageException,
+            DataProcessingException {
         final Instant timestamp = Instant.now();
 
         /* test */
-        export_generic(DATABASE_2_ID, TABLE_1_ID, DATABASE_2, timestamp, USER_2_PRINCIPAL, USER_2_ID, DATABASE_2_USER_1_READ_ACCESS);
+        export_generic(DATABASE_2_ID, TABLE_1_ID, DATABASE_2, timestamp, USER_2_PRINCIPAL);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"export-table-data"})
-    public void export_privateReadWithTimestampInFuture_succeeds() throws TableNotFoundException, DatabaseConnectionException,
-            TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
-            PaginationException, NotAllowedException, QueryMalformedException, UserNotFoundException, IOException {
+    public void export_privateReadWithTimestampInFuture_succeeds() throws TableNotFoundException, NotAllowedException,
+            QueryMalformedException, DatabaseNotFoundException, IOException, FileStorageException,
+            DataProcessingException {
         final Instant timestamp = Instant.now().plus(10, ChronoUnit.DAYS);
 
         /* test */
-        export_generic(DATABASE_2_ID, TABLE_1_ID, DATABASE_2, timestamp, USER_2_PRINCIPAL, USER_2_ID, DATABASE_2_USER_1_READ_ACCESS);
+        export_generic(DATABASE_2_ID, TABLE_1_ID, DATABASE_2, timestamp, USER_2_PRINCIPAL);
     }
 
     /* ################################################################################################### */
@@ -161,10 +159,9 @@ public class ExportEndpointUnitTest extends BaseUnitTest {
     /* ################################################################################################### */
 
     protected void export_generic(Long databaseId, Long tableId, Database database, Instant timestamp,
-                                  Principal principal, UUID userId, DatabaseAccess access) throws IOException,
-            DatabaseNotFoundException, UserNotFoundException, TableNotFoundException, DatabaseConnectionException,
-            TableMalformedException, QueryMalformedException, ImageNotSupportedException, FileStorageException,
-            PaginationException, NotAllowedException {
+                                  Principal principal) throws IOException,
+            DatabaseNotFoundException, TableNotFoundException, QueryMalformedException, FileStorageException,
+            NotAllowedException, DataProcessingException {
         final ExportResource resource = ExportResource.builder()
                 .filename("location.csv")
                 .resource(new InputStreamResource(FileUtils.openInputStream(new File("src/test/resources/weather/location.csv"))))
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/IdentifierEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/IdentifierEndpointUnitTest.java
index 2081cf3cc069a7f22dda63109989308df3fd7347..2b2627cc18e29d8dd69ccce06383dca4ab61a6ee 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/IdentifierEndpointUnitTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/IdentifierEndpointUnitTest.java
@@ -76,10 +76,10 @@ public class IdentifierEndpointUnitTest extends BaseUnitTest {
 
     @Test
     @WithAnonymousUser
-    public void find_json_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
+    public void find_json_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, IOException,
             IdentifierRequestException, UserNotFoundException, QueryStoreException, TableMalformedException,
             DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException,
-            FileStorageException, DataDbSidecarException {
+            FileStorageException, DataProcessingException {
         final String accept = "application/json";
 
         /* mock */
@@ -105,10 +105,10 @@ public class IdentifierEndpointUnitTest extends BaseUnitTest {
 
     @Test
     @WithAnonymousUser
-    public void find_xml_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+    public void find_xml_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, IOException,
+            IdentifierRequestException, UserNotFoundException, QueryStoreException, TableMalformedException,
+            DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException,
+            FileStorageException, DataProcessingException {
         final InputStreamResource resource = new InputStreamResource(FileUtils.openInputStream(
                 new File("src/test/resources/xml/datacite-example-dataset-v4.xml")));
 
@@ -123,10 +123,10 @@ public class IdentifierEndpointUnitTest extends BaseUnitTest {
 
     @Test
     @WithAnonymousUser
-    public void find_csv_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IOException, IdentifierRequestException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+    public void find_csv_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, IOException,
+            IdentifierRequestException, UserNotFoundException, QueryStoreException, TableMalformedException,
+            DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException,
+            FileStorageException, DataProcessingException {
         final InputStreamResource resource = new InputStreamResource(FileUtils.openInputStream(
                 new File("src/test/resources/csv/testdata.csv")));
 
@@ -141,10 +141,10 @@ public class IdentifierEndpointUnitTest extends BaseUnitTest {
 
     @Test
     @WithAnonymousUser
-    public void find_httpRedirect_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, UserNotFoundException, QueryStoreException,
-            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
-            ImageNotSupportedException, FileStorageException, DataDbSidecarException {
+    public void find_httpRedirect_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, IOException,
+            IdentifierRequestException, UserNotFoundException, QueryStoreException, TableMalformedException,
+            DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException,
+            FileStorageException, DataProcessingException {
 
         /* test */
         final ResponseEntity<?> response = generic_find(null, null, null);
@@ -398,7 +398,7 @@ public class IdentifierEndpointUnitTest extends BaseUnitTest {
             throws IdentifierNotFoundException, QueryNotFoundException, IdentifierRequestException,
             UserNotFoundException, QueryStoreException, TableMalformedException, DatabaseConnectionException,
             QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
-            DataDbSidecarException {
+            DataDbSidecarException, DataProcessingException {
 
         /* mock */
         when(identifierService.find(IDENTIFIER_1_ID))
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/PersistenceEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/PersistenceEndpointUnitTest.java
index ad4347d2db4d8d3de0910b2d4235a2b4dc480640..bc0bc1b066aabb257a6b2e5b861a572f2300869a 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/PersistenceEndpointUnitTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/PersistenceEndpointUnitTest.java
@@ -6,13 +6,9 @@ import at.tuwien.annotations.MockOpensearch;
 import at.tuwien.api.identifier.BibliographyTypeDto;
 import at.tuwien.api.identifier.CreatorDto;
 import at.tuwien.api.identifier.IdentifierDto;
-import at.tuwien.api.identifier.IdentifierSaveDto;
 import at.tuwien.entities.identifier.Identifier;
-import at.tuwien.entities.user.User;
 import at.tuwien.exception.*;
-import at.tuwien.service.AccessService;
 import at.tuwien.service.IdentifierService;
-import at.tuwien.service.UserService;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
@@ -34,7 +30,6 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
-import java.security.Principal;
 
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.Mockito.*;
@@ -45,15 +40,9 @@ import static org.mockito.Mockito.*;
 @MockOpensearch
 public class PersistenceEndpointUnitTest extends BaseUnitTest {
 
-    @MockBean
-    private AccessService accessService;
-
     @MockBean
     private IdentifierService identifierService;
 
-    @MockBean
-    private UserService userService;
-
     @Autowired
     private ObjectMapper objectMapper;
 
@@ -69,10 +58,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
 
     @Test
     @WithAnonymousUser
-    public void find_json0_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+    public void find_json0_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, IOException,
+            IdentifierRequestException, UserNotFoundException, QueryStoreException, TableMalformedException,
+            DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException,
+            FileStorageException, DataProcessingException {
         final String accept = "application/json";
         final IdentifierDto compare = objectMapper.readValue(FileUtils.readFileToString(new File("src/test/resources/json/metadata0.json"), StandardCharsets.UTF_8), IdentifierDto.class);
 
@@ -102,10 +91,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
 
     @Test
     @WithAnonymousUser
-    public void find_json1_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+    public void find_json1_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, IOException,
+            IdentifierRequestException, UserNotFoundException, QueryStoreException, TableMalformedException,
+            DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException,
+            FileStorageException, DataProcessingException {
         final String accept = "application/json";
         final IdentifierDto compare = objectMapper.readValue(FileUtils.readFileToString(new File("src/test/resources/json/metadata1.json"), StandardCharsets.UTF_8), IdentifierDto.class);
 
@@ -155,10 +144,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
 
     @Test
     @WithAnonymousUser
-    public void find_csv_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+    public void find_csv_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, IOException,
+            IdentifierRequestException, UserNotFoundException, QueryStoreException, TableMalformedException,
+            DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException,
+            FileStorageException, DataProcessingException {
         final String accept = "text/csv";
         final InputStreamResource compare = new InputStreamResource(FileUtils.openInputStream(new File("src/test/resources/csv/keyboard.csv")));
         final InputStreamResource mock = new InputStreamResource(FileUtils.openInputStream(new File("src/test/resources/csv/keyboard.csv")));
@@ -179,10 +168,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
 
     @Test
     @Disabled("not testable with xml")
-    public void find_xml0_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+    public void find_xml0_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, IOException,
+            IdentifierRequestException, UserNotFoundException, QueryStoreException, TableMalformedException,
+            DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException,
+            FileStorageException, DataProcessingException {
         final String accept = "text/xml";
         final InputStreamResource compare = new InputStreamResource(FileUtils.openInputStream(new File("src/test/resources/xml/metadata0.xml")));
 
@@ -200,10 +189,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
 
     @Test
     @Disabled("not testable with xml")
-    public void find_xml1_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+    public void find_xml1_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, IOException,
+            IdentifierRequestException, UserNotFoundException, QueryStoreException, TableMalformedException,
+            DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException,
+            FileStorageException, DataProcessingException {
         final String accept = "text/xml";
         final InputStreamResource compare = new InputStreamResource(FileUtils.openInputStream(new File("src/test/resources/xml/metadata1.xml")));
 
@@ -222,10 +211,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
 
     @Test
     @WithAnonymousUser
-    public void find_bibliography_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+    public void find_bibliography_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, IOException,
+            IdentifierRequestException, UserNotFoundException, QueryStoreException, TableMalformedException,
+            DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException,
+            FileStorageException, DataProcessingException {
         final String accept = "text/bibliography";
         final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_apa1.txt"),
                 StandardCharsets.UTF_8);
@@ -247,9 +236,9 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
     @Test
     @WithAnonymousUser
     public void find_bibliographyApa0_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+            IOException, IdentifierRequestException, UserNotFoundException, QueryStoreException,
+            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
+            ImageNotSupportedException, FileStorageException, DataProcessingException {
         final String accept = "text/bibliography; style=apa";
         final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_apa0.txt"),
                 StandardCharsets.UTF_8);
@@ -271,9 +260,9 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
     @Test
     @WithAnonymousUser
     public void find_bibliographyApa1_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+            IOException, IdentifierRequestException, UserNotFoundException, QueryStoreException,
+            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
+            ImageNotSupportedException, FileStorageException, DataProcessingException {
         final String accept = "text/bibliography; style=apa";
         final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_apa1.txt"),
                 StandardCharsets.UTF_8);
@@ -295,9 +284,9 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
     @Test
     @WithAnonymousUser
     public void find_bibliographyApa2_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+            IOException, IdentifierRequestException, UserNotFoundException, QueryStoreException,
+            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
+            ImageNotSupportedException, FileStorageException, DataProcessingException {
         final String accept = "text/bibliography; style=apa";
         final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_apa2.txt"),
                 StandardCharsets.UTF_8);
@@ -319,9 +308,9 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
     @Test
     @WithAnonymousUser
     public void find_bibliographyApa3_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+            IOException, IdentifierRequestException, UserNotFoundException, QueryStoreException,
+            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
+            ImageNotSupportedException, FileStorageException, DataProcessingException {
         final String accept = "text/bibliography; style=apa";
         final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_apa3.txt"),
                 StandardCharsets.UTF_8);
@@ -343,9 +332,9 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
     @Test
     @WithAnonymousUser
     public void find_bibliographyApa4_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+            IOException, IdentifierRequestException, UserNotFoundException, QueryStoreException,
+            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
+            ImageNotSupportedException, FileStorageException, DataProcessingException {
         final String accept = "text/bibliography; style=apa";
         final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_apa4.txt"),
                 StandardCharsets.UTF_8);
@@ -367,9 +356,9 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
     @Test
     @WithAnonymousUser
     public void find_bibliographyIeee0_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+            IOException, IdentifierRequestException, UserNotFoundException, QueryStoreException,
+            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
+            ImageNotSupportedException, FileStorageException, DataProcessingException {
         final String accept = "text/bibliography; style=ieee";
         final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_ieee0.txt"),
                 StandardCharsets.UTF_8);
@@ -391,9 +380,9 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
     @Test
     @WithAnonymousUser
     public void find_bibliographyIeee1_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+            IOException, IdentifierRequestException, UserNotFoundException, QueryStoreException,
+            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
+            ImageNotSupportedException, FileStorageException, DataProcessingException {
         final String accept = "text/bibliography; style=ieee";
         final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_ieee1.txt"),
                 StandardCharsets.UTF_8);
@@ -415,9 +404,9 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
     @Test
     @WithAnonymousUser
     public void find_bibliographyIeee2_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+            IOException, IdentifierRequestException, UserNotFoundException, QueryStoreException,
+            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
+            ImageNotSupportedException, FileStorageException, DataProcessingException {
         final String accept = "text/bibliography; style=ieee";
         final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_ieee2.txt"),
                 StandardCharsets.UTF_8);
@@ -439,9 +428,9 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
     @Test
     @WithAnonymousUser
     public void find_bibliographyIeee3_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+            IOException, IdentifierRequestException, UserNotFoundException, QueryStoreException,
+            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
+            ImageNotSupportedException, FileStorageException, DataProcessingException {
         final String accept = "text/bibliography; style=ieee";
         final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_ieee3.txt"),
                 StandardCharsets.UTF_8);
@@ -463,9 +452,9 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
     @Test
     @WithAnonymousUser
     public void find_bibliographyBibtex0_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+            IOException, IdentifierRequestException, UserNotFoundException, QueryStoreException,
+            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
+            ImageNotSupportedException, FileStorageException, DataProcessingException {
         final String accept = "text/bibliography; style=bibtex";
         final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_bibtex0.txt"),
                 StandardCharsets.UTF_8);
@@ -487,9 +476,9 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
     @Test
     @WithAnonymousUser
     public void find_bibliographyBibtex1_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+            IOException, IdentifierRequestException, UserNotFoundException, QueryStoreException,
+            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
+            ImageNotSupportedException, FileStorageException, DataProcessingException {
         final String accept = "text/bibliography; style=bibtex";
         final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_bibtex1.txt"),
                 StandardCharsets.UTF_8);
@@ -511,9 +500,9 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
     @Test
     @WithAnonymousUser
     public void find_bibliographyBibtex2_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+            IOException, IdentifierRequestException, UserNotFoundException, QueryStoreException,
+            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
+            ImageNotSupportedException, FileStorageException, DataProcessingException {
         final String accept = "text/bibliography; style=bibtex";
         final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_bibtex2.txt"),
                 StandardCharsets.UTF_8);
@@ -535,9 +524,9 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
     @Test
     @WithAnonymousUser
     public void find_bibliographyBibtex3_succeeds() throws IdentifierNotFoundException, QueryNotFoundException,
-            RemoteUnavailableException, IdentifierRequestException, IOException, UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException {
+            IOException, IdentifierRequestException, UserNotFoundException, QueryStoreException,
+            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
+            ImageNotSupportedException, FileStorageException, DataProcessingException {
         final String accept = "text/bibliography; style=bibtex";
         final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_bibtex3.txt"),
                 StandardCharsets.UTF_8);
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/QueryEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/QueryEndpointUnitTest.java
index 662c12a02aab1010ad9ae82daa46126ab91631b6..f454704efec8a86aac7b733987735919a4af883e 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/QueryEndpointUnitTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/QueryEndpointUnitTest.java
@@ -8,12 +8,9 @@ import at.tuwien.annotations.MockOpensearch;
 import at.tuwien.api.database.query.ExecuteStatementDto;
 import at.tuwien.api.database.query.QueryResultDto;
 import at.tuwien.entities.database.Database;
-import at.tuwien.entities.database.DatabaseAccess;
 import at.tuwien.exception.*;
 import at.tuwien.querystore.Query;
-import at.tuwien.repository.mdb.ContainerRepository;
 import at.tuwien.repository.mdb.DatabaseRepository;
-import at.tuwien.repository.mdb.ImageRepository;
 import at.tuwien.service.QueryService;
 import at.tuwien.service.StoreService;
 import lombok.extern.log4j.Log4j2;
@@ -35,7 +32,6 @@ import java.io.IOException;
 import java.security.Principal;
 import java.util.List;
 import java.util.Optional;
-import java.util.UUID;
 
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.Mockito.when;
@@ -47,12 +43,6 @@ import static org.mockito.Mockito.when;
 @MockOpensearch
 public class QueryEndpointUnitTest extends BaseUnitTest {
 
-    @MockBean
-    private ImageRepository imageRepository;
-
-    @MockBean
-    private ContainerRepository containerRepository;
-
     @MockBean
     private DatabaseRepository databaseRepository;
 
@@ -72,29 +62,27 @@ public class QueryEndpointUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(QueryMalformedException.class, () -> {
-            generic_execute(DATABASE_3_ID, statement, null, USER_2_PRINCIPAL, DATABASE_3, null);
+            generic_execute(DATABASE_3_ID, statement, USER_2_PRINCIPAL, DATABASE_3);
         });
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"execute-query"})
     public void execute_publicEmptyStatement_fails() {
-        final String statement = null;
 
         /* test */
         assertThrows(QueryMalformedException.class, () -> {
-            generic_execute(DATABASE_3_ID, statement, USER_2_ID, USER_2_PRINCIPAL, DATABASE_3, DATABASE_3_USER_2_READ_ACCESS);
+            generic_execute(DATABASE_3_ID, null, USER_2_PRINCIPAL, DATABASE_3);
         });
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"execute-query"})
     public void execute_publicBlankStatement_fails() {
-        final String statement = "";
 
         /* test */
         assertThrows(QueryMalformedException.class, () -> {
-            generic_execute(DATABASE_3_ID, statement, USER_2_ID, USER_2_PRINCIPAL, DATABASE_3, DATABASE_3_USER_2_READ_ACCESS);
+            generic_execute(DATABASE_3_ID, "", USER_2_PRINCIPAL, DATABASE_3);
         });
     }
 
@@ -105,7 +93,7 @@ public class QueryEndpointUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(QueryMalformedException.class, () -> {
-            generic_execute(DATABASE_3_ID, statement, null, USER_2_PRINCIPAL, DATABASE_3, null);
+            generic_execute(DATABASE_3_ID, statement, USER_2_PRINCIPAL, DATABASE_3);
         });
     }
 
@@ -115,151 +103,143 @@ public class QueryEndpointUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
-            generic_execute(DATABASE_3_ID, QUERY_4_STATEMENT, null, null, DATABASE_3, null);
+            generic_execute(DATABASE_3_ID, QUERY_4_STATEMENT, null, DATABASE_3);
         });
     }
 
     @Test
     @WithMockUser(username = USER_4_USERNAME, authorities = {"execute-query"})
-    public void execute_publicNoAccess_succeeds() throws UserNotFoundException, QueryStoreException, SortException,
-            TableMalformedException, DatabaseConnectionException, NotAllowedException, QueryMalformedException,
-            ColumnParseException, DatabaseNotFoundException, ImageNotSupportedException, PaginationException,
-            KeycloakRemoteException, at.tuwien.exception.AccessDeniedException, QueryNotFoundException {
+    public void execute_publicNoAccess_succeeds() throws UserNotFoundException, AccessDeniedException,
+            QueryStoreException, SortException, TableMalformedException, NotAllowedException, QueryMalformedException,
+            ColumnParseException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
+            PaginationException {
 
         /* test */
-        generic_execute(DATABASE_3_ID, QUERY_4_STATEMENT, null, null, DATABASE_3, null);
+        generic_execute(DATABASE_3_ID, QUERY_4_STATEMENT, null, DATABASE_3);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"execute-query"})
-    public void execute_publicRead_succeeds() throws UserNotFoundException, QueryStoreException, TableMalformedException,
-            DatabaseConnectionException, QueryMalformedException, ColumnParseException, DatabaseNotFoundException,
-            ImageNotSupportedException, SortException, NotAllowedException, PaginationException,
-            KeycloakRemoteException, at.tuwien.exception.AccessDeniedException, QueryNotFoundException {
+    public void execute_publicRead_succeeds() throws UserNotFoundException, AccessDeniedException, QueryStoreException,
+            SortException, TableMalformedException, NotAllowedException, QueryMalformedException, ColumnParseException,
+            QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException, PaginationException {
 
         /* test */
-        generic_execute(DATABASE_3_ID, QUERY_4_STATEMENT, USER_2_ID, USER_2_PRINCIPAL, DATABASE_3, DATABASE_3_USER_2_WRITE_ALL_ACCESS);
+        generic_execute(DATABASE_3_ID, QUERY_4_STATEMENT, USER_2_PRINCIPAL, DATABASE_3);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"execute-query"})
-    public void execute_publicWriteOwn_succeeds() throws UserNotFoundException, QueryStoreException, TableMalformedException,
-            DatabaseConnectionException, QueryMalformedException, ColumnParseException, DatabaseNotFoundException,
-            ImageNotSupportedException, SortException, NotAllowedException, PaginationException,
-            KeycloakRemoteException, at.tuwien.exception.AccessDeniedException, QueryNotFoundException {
+    public void execute_publicWriteOwn_succeeds() throws UserNotFoundException, AccessDeniedException,
+            QueryStoreException, SortException, TableMalformedException, NotAllowedException, QueryMalformedException,
+            ColumnParseException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
+            PaginationException {
 
         /* test */
-        generic_execute(DATABASE_3_ID, QUERY_4_STATEMENT, USER_2_ID, USER_2_PRINCIPAL, DATABASE_3, DATABASE_3_USER_2_WRITE_ALL_ACCESS);
+        generic_execute(DATABASE_3_ID, QUERY_4_STATEMENT, USER_2_PRINCIPAL, DATABASE_3);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"execute-query"})
-    public void execute_publicWriteAll_succeeds() throws UserNotFoundException, QueryStoreException, TableMalformedException,
-            DatabaseConnectionException, QueryMalformedException, ColumnParseException, DatabaseNotFoundException,
-            ImageNotSupportedException, SortException, NotAllowedException, PaginationException,
-            KeycloakRemoteException, at.tuwien.exception.AccessDeniedException, QueryNotFoundException {
+    public void execute_publicWriteAll_succeeds() throws UserNotFoundException, AccessDeniedException,
+            QueryStoreException, SortException, TableMalformedException, NotAllowedException, QueryMalformedException,
+            ColumnParseException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException, PaginationException {
 
         /* test */
-        generic_execute(DATABASE_3_ID, QUERY_4_STATEMENT, USER_2_ID, USER_2_PRINCIPAL, DATABASE_3, DATABASE_3_USER_2_WRITE_ALL_ACCESS);
+        generic_execute(DATABASE_3_ID, QUERY_4_STATEMENT, USER_2_PRINCIPAL, DATABASE_3);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"execute-query"})
-    public void execute_publicOwner_succeeds() throws UserNotFoundException, QueryStoreException, TableMalformedException,
-            DatabaseConnectionException, QueryMalformedException, ColumnParseException, DatabaseNotFoundException,
-            ImageNotSupportedException, SortException, NotAllowedException, PaginationException,
-            KeycloakRemoteException, at.tuwien.exception.AccessDeniedException, QueryNotFoundException {
+    public void execute_publicOwner_succeeds() throws UserNotFoundException, AccessDeniedException, QueryStoreException,
+            SortException, TableMalformedException, NotAllowedException, QueryMalformedException, ColumnParseException,
+            QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException, PaginationException {
 
         /* test */
-        generic_execute(DATABASE_3_ID, QUERY_4_STATEMENT, USER_2_ID, USER_2_PRINCIPAL, DATABASE_3, DATABASE_3_USER_2_WRITE_ALL_ACCESS);
+        generic_execute(DATABASE_3_ID, QUERY_4_STATEMENT, USER_2_PRINCIPAL, DATABASE_3);
     }
 
     @Test
     @WithAnonymousUser
-    public void reExecute_publicAnonymized_succeeds() throws UserNotFoundException, QueryStoreException, SortException,
-            DatabaseConnectionException, TableMalformedException, NotAllowedException, QueryMalformedException,
-            QueryNotFoundException, ColumnParseException, DatabaseNotFoundException, ImageNotSupportedException,
-            PaginationException, at.tuwien.exception.AccessDeniedException {
+    public void reExecute_publicAnonymized_succeeds() throws AccessDeniedException, QueryStoreException, SortException,
+            TableMalformedException, NotAllowedException, QueryMalformedException, QueryNotFoundException,
+            ColumnParseException, DatabaseNotFoundException, ImageNotSupportedException, PaginationException {
 
         /* test */
         generic_reExecute(DATABASE_3_ID, QUERY_4_ID, QUERY_4, QUERY_4_RESULT_ID, QUERY_4_RESULT_DTO,
-                null, null, DATABASE_3, null);
+                null, DATABASE_3);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"execute-query"})
-    public void reExecute_publicRead_succeeds() throws UserNotFoundException, QueryStoreException, TableMalformedException,
-            DatabaseConnectionException, QueryMalformedException, ColumnParseException, DatabaseNotFoundException,
-            ImageNotSupportedException, SortException, NotAllowedException,
-            PaginationException, QueryNotFoundException, at.tuwien.exception.AccessDeniedException {
+    public void reExecute_publicRead_succeeds() throws AccessDeniedException, QueryStoreException, SortException,
+            TableMalformedException, NotAllowedException, QueryMalformedException, QueryNotFoundException,
+            ColumnParseException, DatabaseNotFoundException, ImageNotSupportedException, PaginationException {
 
         /* test */
         generic_reExecute(DATABASE_3_ID, QUERY_4_ID, QUERY_4, QUERY_4_RESULT_ID, QUERY_4_RESULT_DTO,
-                USER_2_ID, USER_2_PRINCIPAL, DATABASE_3, DATABASE_3_USER_1_READ_ACCESS);
+                USER_2_PRINCIPAL, DATABASE_3);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"execute-query"})
-    public void reExecute_public_succeeds() throws UserNotFoundException, QueryStoreException, TableMalformedException,
-            DatabaseConnectionException, QueryMalformedException, ColumnParseException, DatabaseNotFoundException,
-            ImageNotSupportedException, SortException, NotAllowedException,
-            PaginationException, QueryNotFoundException, at.tuwien.exception.AccessDeniedException {
+    public void reExecute_public_succeeds() throws AccessDeniedException, QueryStoreException, SortException,
+            TableMalformedException, NotAllowedException, QueryMalformedException, QueryNotFoundException,
+            ColumnParseException, DatabaseNotFoundException, ImageNotSupportedException, PaginationException {
 
         /* test */
         generic_reExecute(DATABASE_3_ID, QUERY_4_ID, QUERY_4, QUERY_4_RESULT_ID, QUERY_4_RESULT_DTO,
-                USER_2_ID, USER_2_PRINCIPAL, DATABASE_3, DATABASE_3_USER_1_WRITE_OWN_ACCESS);
+                USER_2_PRINCIPAL, DATABASE_3);
     }
 
     @Test
     @WithAnonymousUser
-    public void export_publicAnonymized_succeeds() throws UserNotFoundException, QueryStoreException,
-            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
-            ImageNotSupportedException, QueryNotFoundException, FileStorageException,
-            IOException, NotAllowedException {
+    public void export_publicAnonymized_succeeds() throws QueryStoreException, NotAllowedException,
+            QueryMalformedException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
+            IOException, FileStorageException, DataProcessingException {
 
         /* test */
-        export_generic(DATABASE_3_ID, QUERY_3_ID, null, null, DATABASE_3, null, null, HttpStatus.OK);
+        export_generic(DATABASE_3_ID, QUERY_3_ID, null, DATABASE_3, null, HttpStatus.OK);
     }
 
     @Test
     @WithAnonymousUser
-    public void export_publicAnonymizedInvalidFormat_fails() throws UserNotFoundException, QueryStoreException, DatabaseConnectionException, TableMalformedException, NotAllowedException, QueryMalformedException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException, IOException, FileStorageException, ContainerNotFoundException {
+    public void export_publicAnonymizedInvalidFormat_fails() throws QueryStoreException, NotAllowedException,
+            QueryMalformedException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
+            IOException, FileStorageException, DataProcessingException {
 
         /* test */
-        export_generic(DATABASE_3_ID, QUERY_3_ID, null, null, DATABASE_3, null, "application/json", HttpStatus.NOT_IMPLEMENTED);
+        export_generic(DATABASE_3_ID, QUERY_3_ID, null, DATABASE_3, "application/json", HttpStatus.NOT_IMPLEMENTED);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"export-query-data"})
-    public void export_publicRead_succeeds() throws UserNotFoundException, QueryStoreException,
-            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
-            ImageNotSupportedException, QueryNotFoundException, FileStorageException,
-            IOException, NotAllowedException {
+    public void export_publicRead_succeeds() throws QueryStoreException, NotAllowedException, QueryMalformedException,
+            QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException, IOException,
+            FileStorageException, DataProcessingException {
 
         /* test */
-        export_generic(DATABASE_3_ID, QUERY_3_ID, USER_2_ID, USER_2_PRINCIPAL, DATABASE_3, DATABASE_3_USER_1_READ_ACCESS, null, HttpStatus.OK);
+        export_generic(DATABASE_3_ID, QUERY_3_ID, USER_2_PRINCIPAL, DATABASE_3, null, HttpStatus.OK);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"export-query-data"})
-    public void export_publicWriteOwn_succeeds() throws UserNotFoundException, QueryStoreException,
-            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
-            ImageNotSupportedException, QueryNotFoundException, FileStorageException,
-            IOException, NotAllowedException {
+    public void export_publicWriteOwn_succeeds() throws QueryStoreException, NotAllowedException,
+            QueryMalformedException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
+            IOException, FileStorageException, DataProcessingException {
 
         /* test */
-        export_generic(DATABASE_3_ID, QUERY_4_ID, USER_2_ID, USER_2_PRINCIPAL, DATABASE_3, DATABASE_3_USER_1_WRITE_OWN_ACCESS, null, HttpStatus.OK);
+        export_generic(DATABASE_3_ID, QUERY_4_ID, USER_2_PRINCIPAL, DATABASE_3, null, HttpStatus.OK);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"export-query-data"})
-    public void export_publicWriteAll_succeeds() throws UserNotFoundException, QueryStoreException,
-            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
-            ImageNotSupportedException, QueryNotFoundException, FileStorageException,
-            IOException, NotAllowedException {
+    public void export_publicWriteAll_succeeds() throws QueryStoreException, NotAllowedException,
+            QueryMalformedException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
+            IOException, FileStorageException, DataProcessingException {
 
         /* test */
-        export_generic(DATABASE_3_ID, QUERY_4_ID, USER_2_ID, USER_2_PRINCIPAL, DATABASE_3, DATABASE_3_USER_1_WRITE_ALL_ACCESS, null, HttpStatus.OK);
+        export_generic(DATABASE_3_ID, QUERY_4_ID, USER_2_PRINCIPAL, DATABASE_3, null, HttpStatus.OK);
     }
 
     /* ################################################################################################### */
@@ -269,68 +249,66 @@ public class QueryEndpointUnitTest extends BaseUnitTest {
     @Test
     @WithAnonymousUser
     public void execute_privateAnonymized_fails() {
-        final Principal principal = null;
 
         /* test */
         assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
-            generic_execute(DATABASE_2_ID, QUERY_1_STATEMENT, null, principal, DATABASE_2, null);
+            generic_execute(DATABASE_2_ID, QUERY_1_STATEMENT, null, DATABASE_2);
         });
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"execute-query"})
-    public void execute_privateRead_succeeds() throws UserNotFoundException, QueryStoreException, TableMalformedException,
-            DatabaseConnectionException, QueryMalformedException, ColumnParseException, DatabaseNotFoundException,
-            ImageNotSupportedException, SortException, NotAllowedException, PaginationException,
-            KeycloakRemoteException, at.tuwien.exception.AccessDeniedException, QueryNotFoundException {
+    public void execute_privateRead_succeeds() throws UserNotFoundException, AccessDeniedException, QueryStoreException,
+            SortException, TableMalformedException, NotAllowedException, QueryMalformedException, ColumnParseException,
+            QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException, PaginationException {
 
         /* mock */
         DATABASE_2.setAccesses(List.of(DATABASE_2_USER_2_READ_ACCESS));
 
         /* test */
-        generic_execute(DATABASE_2_ID, QUERY_1_STATEMENT, USER_2_ID, USER_2_PRINCIPAL, DATABASE_2, DATABASE_2_USER_1_READ_ACCESS);
+        generic_execute(DATABASE_2_ID, QUERY_1_STATEMENT, USER_2_PRINCIPAL, DATABASE_2);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"execute-query"})
-    public void execute_privateWriteOwn_succeeds() throws UserNotFoundException, QueryStoreException, TableMalformedException,
-            DatabaseConnectionException, QueryMalformedException, ColumnParseException, DatabaseNotFoundException,
-            ImageNotSupportedException, SortException, NotAllowedException, PaginationException,
-            KeycloakRemoteException, at.tuwien.exception.AccessDeniedException, QueryNotFoundException {
+    public void execute_privateWriteOwn_succeeds() throws UserNotFoundException, AccessDeniedException,
+            QueryStoreException, SortException, TableMalformedException, NotAllowedException, QueryMalformedException,
+            ColumnParseException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
+            PaginationException {
 
         /* mock */
         DATABASE_2.setAccesses(List.of(DATABASE_2_USER_2_WRITE_OWN_ACCESS));
 
         /* test */
-        generic_execute(DATABASE_2_ID, QUERY_1_STATEMENT, USER_2_ID, USER_2_PRINCIPAL, DATABASE_2, DATABASE_2_USER_1_WRITE_OWN_ACCESS);
+        generic_execute(DATABASE_2_ID, QUERY_1_STATEMENT, USER_2_PRINCIPAL, DATABASE_2);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"execute-query"})
-    public void execute_privateWriteAll_succeeds() throws UserNotFoundException, QueryStoreException, TableMalformedException,
-            DatabaseConnectionException, QueryMalformedException, ColumnParseException, DatabaseNotFoundException,
-            ImageNotSupportedException, SortException, NotAllowedException, PaginationException,
-            KeycloakRemoteException, at.tuwien.exception.AccessDeniedException, QueryNotFoundException {
+    public void execute_privateWriteAll_succeeds() throws UserNotFoundException, AccessDeniedException,
+            QueryStoreException, SortException, TableMalformedException, NotAllowedException, QueryMalformedException,
+            ColumnParseException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
+            PaginationException {
 
         /* mock */
         DATABASE_2.setAccesses(List.of(DATABASE_2_USER_2_WRITE_ALL_ACCESS));
 
         /* test */
-        generic_execute(DATABASE_2_ID, QUERY_1_STATEMENT, USER_2_ID, USER_2_PRINCIPAL, DATABASE_2, DATABASE_2_USER_1_WRITE_ALL_ACCESS);
+        generic_execute(DATABASE_2_ID, QUERY_1_STATEMENT, USER_2_PRINCIPAL, DATABASE_2);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"execute-query"})
-    public void execute_privateOwner_succeeds() throws UserNotFoundException, QueryStoreException, TableMalformedException,
-            DatabaseConnectionException, QueryMalformedException, ColumnParseException, DatabaseNotFoundException,
-            ImageNotSupportedException, SortException, NotAllowedException, PaginationException,
-            KeycloakRemoteException, at.tuwien.exception.AccessDeniedException, QueryNotFoundException {
+    public void execute_privateOwner_succeeds() throws UserNotFoundException, AccessDeniedException,
+            QueryStoreException, SortException, TableMalformedException, NotAllowedException, QueryMalformedException,
+            ColumnParseException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
+            PaginationException {
 
         /* mock */
         DATABASE_2.setAccesses(List.of(DATABASE_2_USER_1_WRITE_ALL_ACCESS));
 
         /* test */
-        generic_execute(DATABASE_2_ID, QUERY_1_STATEMENT, USER_1_ID, USER_1_PRINCIPAL, DATABASE_2, DATABASE_2_USER_1_WRITE_ALL_ACCESS);
+        generic_execute(DATABASE_2_ID, QUERY_1_STATEMENT, USER_1_PRINCIPAL, DATABASE_2);
     }
 
     @Test
@@ -340,53 +318,51 @@ public class QueryEndpointUnitTest extends BaseUnitTest {
         /* test */
         assertThrows(NotAllowedException.class, () -> {
             generic_reExecute(DATABASE_2_ID, QUERY_1_ID, QUERY_1, QUERY_1_RESULT_ID, QUERY_1_RESULT_DTO,
-                    null, null, DATABASE_2, null);
+                    null, DATABASE_2);
         });
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"execute-query"})
-    public void reExecute_privateRead_succeeds() throws UserNotFoundException, QueryStoreException, TableMalformedException,
-            DatabaseConnectionException, QueryMalformedException, ColumnParseException, DatabaseNotFoundException,
-            ImageNotSupportedException, SortException, NotAllowedException, PaginationException, QueryNotFoundException,
-            at.tuwien.exception.AccessDeniedException {
+    public void reExecute_privateRead_succeeds() throws AccessDeniedException, QueryStoreException, SortException,
+            TableMalformedException, NotAllowedException, QueryMalformedException, QueryNotFoundException,
+            ColumnParseException, DatabaseNotFoundException, ImageNotSupportedException, PaginationException {
 
         /* mock */
         DATABASE_2.setAccesses(List.of(DATABASE_2_USER_2_READ_ACCESS));
 
         /* test */
         generic_reExecute(DATABASE_2_ID, QUERY_1_ID, QUERY_1, QUERY_1_RESULT_ID, QUERY_1_RESULT_DTO,
-                USER_2_ID, USER_2_PRINCIPAL, DATABASE_2, DATABASE_2_USER_1_READ_ACCESS);
+                USER_2_PRINCIPAL, DATABASE_2);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"execute-query"})
-    public void reExecute_privateWriteOwn_succeeds() throws UserNotFoundException, QueryStoreException,
-            TableMalformedException, DatabaseConnectionException, QueryMalformedException, ColumnParseException,
-            DatabaseNotFoundException, ImageNotSupportedException, SortException, NotAllowedException,
-            PaginationException, QueryNotFoundException, at.tuwien.exception.AccessDeniedException {
+    public void reExecute_privateWriteOwn_succeeds() throws AccessDeniedException, QueryStoreException, SortException,
+            TableMalformedException, NotAllowedException, QueryMalformedException, QueryNotFoundException,
+            ColumnParseException, DatabaseNotFoundException, ImageNotSupportedException, PaginationException {
 
         /* mock */
         DATABASE_2.setAccesses(List.of(DATABASE_2_USER_2_WRITE_OWN_ACCESS));
 
         /* test */
         generic_reExecute(DATABASE_2_ID, QUERY_1_ID, QUERY_1, QUERY_1_RESULT_ID, QUERY_1_RESULT_DTO,
-                USER_2_ID, USER_2_PRINCIPAL, DATABASE_2, DATABASE_2_USER_1_WRITE_OWN_ACCESS);
+                USER_2_PRINCIPAL, DATABASE_2);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"execute-query"})
-    public void reExecute_privateWriteAll_succeeds() throws UserNotFoundException, QueryStoreException,
-            TableMalformedException, DatabaseConnectionException, QueryMalformedException, ColumnParseException,
-            DatabaseNotFoundException, ImageNotSupportedException, SortException, NotAllowedException,
-            PaginationException, QueryNotFoundException, at.tuwien.exception.AccessDeniedException {
+    public void reExecute_privateWriteAll_succeeds() throws QueryStoreException, TableMalformedException,
+            QueryMalformedException, ColumnParseException, DatabaseNotFoundException, ImageNotSupportedException,
+            SortException, NotAllowedException, PaginationException, QueryNotFoundException,
+            at.tuwien.exception.AccessDeniedException {
 
         /* mock */
         DATABASE_2.setAccesses(List.of(DATABASE_2_USER_2_WRITE_ALL_ACCESS));
 
         /* test */
         generic_reExecute(DATABASE_2_ID, QUERY_1_ID, QUERY_1, QUERY_1_RESULT_ID, QUERY_1_RESULT_DTO,
-                USER_2_ID, USER_2_PRINCIPAL, DATABASE_2, DATABASE_2_USER_1_WRITE_ALL_ACCESS);
+                USER_2_PRINCIPAL, DATABASE_2);
     }
 
     @Test
@@ -395,64 +371,59 @@ public class QueryEndpointUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(NotAllowedException.class, () -> {
-            export_generic(DATABASE_2_ID, QUERY_1_ID, null, null, DATABASE_2, null, null, HttpStatus.OK);
+            export_generic(DATABASE_2_ID, QUERY_1_ID, null, DATABASE_2, null, HttpStatus.OK);
         });
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"export-query-data"})
-    public void export_privateInvalidFormat_fails() throws UserNotFoundException, QueryStoreException,
-            DatabaseConnectionException, TableMalformedException, NotAllowedException, QueryMalformedException,
-            QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException, IOException,
-            FileStorageException {
+    public void export_privateInvalidFormat_fails() throws QueryStoreException, NotAllowedException,
+            QueryMalformedException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
+            IOException, FileStorageException, DataProcessingException {
 
         /* test */
-        export_generic(DATABASE_2_ID, QUERY_1_ID, USER_2_ID, USER_2_PRINCIPAL, DATABASE_2, DATABASE_2_USER_2_READ_ACCESS, "application/json", HttpStatus.NOT_IMPLEMENTED);
+        export_generic(DATABASE_2_ID, QUERY_1_ID, USER_2_PRINCIPAL, DATABASE_2, "application/json", HttpStatus.NOT_IMPLEMENTED);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"export-query-data"})
-    public void export_privateRead_succeeds() throws UserNotFoundException, QueryStoreException,
-            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
-            ImageNotSupportedException, NotAllowedException, QueryNotFoundException, FileStorageException,
-            IOException {
+    public void export_privateRead_succeeds() throws QueryStoreException, NotAllowedException, QueryMalformedException,
+            QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException, IOException,
+            FileStorageException, DataProcessingException {
 
         /* test */
-        export_generic(DATABASE_2_ID, QUERY_1_ID, USER_2_ID, USER_2_PRINCIPAL, DATABASE_2, DATABASE_2_USER_1_READ_ACCESS, null, HttpStatus.OK);
+        export_generic(DATABASE_2_ID, QUERY_1_ID, USER_2_PRINCIPAL, DATABASE_2, null, HttpStatus.OK);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"export-query-data"})
-    public void export_privateWriteOwn_succeeds() throws UserNotFoundException, QueryStoreException,
-            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
-            ImageNotSupportedException, NotAllowedException, QueryNotFoundException, FileStorageException,
-            IOException {
+    public void export_privateWriteOwn_succeeds() throws QueryStoreException, NotAllowedException,
+            QueryMalformedException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
+            IOException, FileStorageException, DataProcessingException {
 
         /* test */
-        export_generic(DATABASE_2_ID, QUERY_1_ID, USER_2_ID, USER_2_PRINCIPAL, DATABASE_2, DATABASE_2_USER_1_WRITE_OWN_ACCESS, null, HttpStatus.OK);
+        export_generic(DATABASE_2_ID, QUERY_1_ID, USER_2_PRINCIPAL, DATABASE_2, null, HttpStatus.OK);
     }
 
     @Test
     @WithMockUser(username = USER_2_USERNAME, authorities = {"export-query-data"})
-    public void export_privateWriteAll_succeeds() throws UserNotFoundException, QueryStoreException,
-            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
-            ImageNotSupportedException, NotAllowedException, QueryNotFoundException, FileStorageException,
-            IOException {
+    public void export_privateWriteAll_succeeds() throws QueryStoreException, NotAllowedException,
+            QueryMalformedException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
+            IOException, FileStorageException, DataProcessingException {
 
         /* test */
-        export_generic(DATABASE_2_ID, QUERY_1_ID, USER_2_ID, USER_2_PRINCIPAL, DATABASE_2, DATABASE_2_USER_1_WRITE_ALL_ACCESS, null, HttpStatus.OK);
+        export_generic(DATABASE_2_ID, QUERY_1_ID, USER_2_PRINCIPAL, DATABASE_2, null, HttpStatus.OK);
     }
 
     /* ################################################################################################### */
     /* ## GENERIC TEST CASES                                                                            ## */
     /* ################################################################################################### */
 
-    protected void generic_execute(Long databaseId, String statement, UUID userId, Principal principal,
-                                   Database database, DatabaseAccess access) throws UserNotFoundException,
-            QueryStoreException, TableMalformedException, DatabaseConnectionException,
-            QueryMalformedException, ColumnParseException, DatabaseNotFoundException, ImageNotSupportedException,
-            SortException, NotAllowedException, PaginationException, KeycloakRemoteException,
-            at.tuwien.exception.AccessDeniedException, QueryNotFoundException {
+    protected void generic_execute(Long databaseId, String statement, Principal principal, Database database)
+            throws UserNotFoundException, QueryStoreException, TableMalformedException, QueryMalformedException,
+            ColumnParseException, DatabaseNotFoundException, ImageNotSupportedException, SortException,
+            NotAllowedException, PaginationException, at.tuwien.exception.AccessDeniedException,
+            QueryNotFoundException {
         final ExecuteStatementDto request = ExecuteStatementDto.builder()
                 .statement(statement)
                 .build();
@@ -481,9 +452,8 @@ public class QueryEndpointUnitTest extends BaseUnitTest {
     }
 
     protected void generic_reExecute(Long databaseId, Long queryId, Query query, Long resultId,
-                                     QueryResultDto result, UUID userId, Principal principal, Database database,
-                                     DatabaseAccess access) throws UserNotFoundException, QueryStoreException,
-            DatabaseConnectionException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
+                                     QueryResultDto result, Principal principal, Database database)
+            throws QueryStoreException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
             TableMalformedException, QueryMalformedException, ColumnParseException, SortException, NotAllowedException,
             PaginationException, at.tuwien.exception.AccessDeniedException {
         final Long page = 0L;
@@ -507,11 +477,10 @@ public class QueryEndpointUnitTest extends BaseUnitTest {
         assertEquals(resultId, response.getBody().getId());
     }
 
-    protected void export_generic(Long databaseId, Long queryId, UUID userId, Principal principal,
-                                  Database database, DatabaseAccess access, String accept, HttpStatus status) throws IOException,
-            UserNotFoundException, QueryStoreException, DatabaseConnectionException, QueryNotFoundException,
-            DatabaseNotFoundException, ImageNotSupportedException, TableMalformedException, QueryMalformedException,
-            FileStorageException, NotAllowedException {
+    protected void export_generic(Long databaseId, Long queryId, Principal principal, Database database, String accept,
+                                  HttpStatus status) throws IOException, QueryStoreException, QueryNotFoundException,
+            DatabaseNotFoundException, ImageNotSupportedException, QueryMalformedException, FileStorageException,
+            NotAllowedException, DataProcessingException {
         final ExportResource resource = ExportResource.builder()
                 .filename("location.csv")
                 .resource(new InputStreamResource(FileUtils.openInputStream(new File("src/test/resources/weather/location.csv"))))
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableDataEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableDataEndpointUnitTest.java
index de3269a1671045b98f59556a4b082a875b91bb8d..933d4ba78aefde918ecbbaa7f4f63fb5c5249871 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableDataEndpointUnitTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableDataEndpointUnitTest.java
@@ -136,9 +136,9 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
 
     @Test
     @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"})
-    public void import_publicWriteAll_succeeds() throws UserNotFoundException, TableNotFoundException, NotAllowedException,
-            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
-            ImageNotSupportedException, AccessDeniedException, DataDbSidecarException {
+    public void import_publicWriteAll_succeeds() throws TableNotFoundException, AccessDeniedException,
+            TableMalformedException, NotAllowedException, DatabaseNotFoundException, DataDbSidecarException,
+            DataProcessingException {
 
         /* test */
         generic_import(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, USER_1_ID,
@@ -147,9 +147,9 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
 
     @Test
     @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"})
-    public void import_privateWriteAll_succeeds() throws UserNotFoundException, TableNotFoundException, NotAllowedException,
-            TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
-            ImageNotSupportedException, AccessDeniedException, DataDbSidecarException {
+    public void import_privateWriteAll_succeeds() throws TableNotFoundException, AccessDeniedException,
+            TableMalformedException, NotAllowedException, DatabaseNotFoundException, DataDbSidecarException,
+            DataProcessingException {
 
         /* test */
         generic_import(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, USER_1_ID,
@@ -224,9 +224,8 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
 
     @Test
     @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"})
-    public void insert_publicWriteAll_succeeds() throws UserNotFoundException, TableNotFoundException,
-            NotAllowedException, TableMalformedException, DatabaseConnectionException, DatabaseNotFoundException,
-            ImageNotSupportedException, ContainerNotFoundException, AccessDeniedException {
+    public void insert_publicWriteAll_succeeds() throws TableNotFoundException, AccessDeniedException,
+            TableMalformedException, NotAllowedException, DatabaseNotFoundException {
 
         /* test */
         generic_insert(DATABASE_3_ID, TABLE_8_ID, DATABASE_3, TABLE_8, USER_1_ID,
@@ -235,9 +234,8 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
 
     @Test
     @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"})
-    public void insert_privateWriteAll_succeeds() throws UserNotFoundException, TableNotFoundException,
-            NotAllowedException, TableMalformedException, DatabaseConnectionException, DatabaseNotFoundException,
-            ImageNotSupportedException, ContainerNotFoundException, AccessDeniedException {
+    public void insert_privateWriteAll_succeeds() throws TableNotFoundException, AccessDeniedException,
+            TableMalformedException, NotAllowedException, DatabaseNotFoundException {
 
         /* test */
         generic_insert(DATABASE_1_ID, TABLE_1_ID, DATABASE_1, TABLE_1, USER_1_ID, DATABASE_1_USER_1_WRITE_ALL_ACCESS, TABLE_1_CSV_DTO, USER_1_PRINCIPAL);
@@ -245,9 +243,8 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
 
     @Test
     @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"})
-    public void insert_privateDataNull_fails() throws UserNotFoundException, TableNotFoundException,
-            NotAllowedException, TableMalformedException, DatabaseConnectionException, DatabaseNotFoundException,
-            ImageNotSupportedException, ContainerNotFoundException, AccessDeniedException {
+    public void insert_privateDataNull_fails() throws TableNotFoundException, AccessDeniedException,
+            TableMalformedException, NotAllowedException, DatabaseNotFoundException {
 
         /* test */
         generic_insert(DATABASE_1_ID, TABLE_1_ID, DATABASE_1, TABLE_1, USER_1_ID, DATABASE_1_USER_1_WRITE_ALL_ACCESS, null, USER_1_PRINCIPAL);
@@ -369,10 +366,9 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     @MethodSource("getAll_succeeds_parameters")
     public void getAll_succeeds(String test, Long databaseId, Long tableId, Database database, Table table, UUID userId,
                                 DatabaseAccess access, Principal principal, Instant timestamp, Long page, Long size,
-                                SortType sortDirection, String sortColumn) throws UserNotFoundException,
-            TableNotFoundException, SortException, TableMalformedException, NotAllowedException,
-            DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException,
-            PaginationException, AccessDeniedException {
+                                SortType sortDirection, String sortColumn) throws TableNotFoundException, SortException,
+            TableMalformedException, NotAllowedException, QueryMalformedException, DatabaseNotFoundException,
+            ImageNotSupportedException, PaginationException, AccessDeniedException {
 
         /* test */
         generic_getAll(databaseId, tableId, database, table, userId, access, principal, timestamp,
@@ -409,9 +405,8 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     @MethodSource("getAll_succeeds_parameters")
     public void getCount_succeeds(String test, Long databaseId, Long tableId, Database database, Table table,
                                   UUID userId, DatabaseAccess access, Principal principal, Instant timestamp)
-            throws UserNotFoundException, TableNotFoundException, QueryStoreException, TableMalformedException,
-            NotAllowedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
-            ImageNotSupportedException, AccessDeniedException {
+            throws TableNotFoundException, QueryStoreException, TableMalformedException, NotAllowedException,
+            QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException, AccessDeniedException {
 
         /* test */
         generic_getCount(databaseId, tableId, database, table, userId, access, principal, timestamp);
@@ -424,7 +419,8 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
 
     public void generic_import(Long databaseId, Database database, Long tableId, Table table, UUID userId,
                                DatabaseAccess access, Principal principal) throws DatabaseNotFoundException,
-            TableNotFoundException, AccessDeniedException, TableMalformedException, NotAllowedException, DataDbSidecarException {
+            TableNotFoundException, AccessDeniedException, TableMalformedException, NotAllowedException,
+            DataDbSidecarException, DataProcessingException {
         final ImportDto request = ImportDto.builder().location("test:csv/csv_01.csv").build();
 
         /* mock */
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/BrokerServiceGatewayTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/BrokerServiceGatewayTest.java
deleted file mode 100644
index e73cc99df0b6af44e2d1634df68db2c1c9da95c9..0000000000000000000000000000000000000000
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/BrokerServiceGatewayTest.java
+++ /dev/null
@@ -1,178 +0,0 @@
-package at.tuwien.gateway;
-
-import at.tuwien.BaseUnitTest;
-import at.tuwien.annotations.MockAmqp;
-import at.tuwien.annotations.MockOpensearch;
-import at.tuwien.exception.BrokerRemoteException;
-import at.tuwien.exception.BrokerVirtualHostModificationException;
-import at.tuwien.exception.BrokerVirtualHostGrantException;
-import lombok.extern.log4j.Log4j2;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
-import org.springframework.web.client.RestTemplate;
-
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.Mockito.*;
-
-@Log4j2
-@SpringBootTest
-@ExtendWith(SpringExtension.class)
-@MockAmqp
-@MockOpensearch
-public class BrokerServiceGatewayTest extends BaseUnitTest {
-
-    @MockBean
-    @Qualifier("brokerRestTemplate")
-    private RestTemplate restTemplate;
-
-    @Autowired
-    private BrokerServiceGateway brokerServiceGateway;
-
-    @Test
-    public void createVirtualHost_succeeds() throws BrokerVirtualHostModificationException, BrokerRemoteException {
-        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.CREATED)
-                .build();
-
-        /* mock */
-        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)))
-                .thenReturn(mock);
-
-        /* test */
-        brokerServiceGateway.createVirtualHost(VIRTUAL_HOST_CREATE_DTO);
-    }
-
-    @Test
-    public void createVirtualHost_fails() {
-        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.NO_CONTENT)
-                .build();
-
-        /* mock */
-        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)))
-                .thenReturn(mock);
-
-        /* test */
-        assertThrows(BrokerVirtualHostModificationException.class, () -> {
-            brokerServiceGateway.createVirtualHost(VIRTUAL_HOST_CREATE_DTO);
-        });
-    }
-
-    @Test
-    public void grantPermission_exchangeNoRightsBefore_succeeds() throws BrokerVirtualHostGrantException, BrokerRemoteException {
-        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.CREATED)
-                .build();
-
-        /* mock */
-        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
-                .thenReturn(mock);
-
-        /* test */
-        brokerServiceGateway.grantPermission(USER_1_USERNAME, VIRTUAL_HOST_EXCHANGE_UPDATE_DTO);
-    }
-
-    @Test
-    public void grantPermission_exchangeRightsSame_succeeds() throws BrokerVirtualHostGrantException, BrokerRemoteException {
-        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.NO_CONTENT)
-                .build();
-
-        /* mock */
-        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
-                .thenReturn(mock);
-
-        /* test */
-        brokerServiceGateway.grantPermission(USER_1_USERNAME, VIRTUAL_HOST_EXCHANGE_UPDATE_DTO);
-    }
-
-    @Test
-    public void grantPermission_invalidResponseCode_fails() {
-        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.UNAUTHORIZED)
-                .build();
-
-        /* mock */
-        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
-                .thenReturn(mock);
-
-        /* test */
-        assertThrows(BrokerVirtualHostGrantException.class, () -> {
-            brokerServiceGateway.grantPermission(USER_1_USERNAME, VIRTUAL_HOST_EXCHANGE_UPDATE_DTO);
-        });
-    }
-
-    @Test
-    public void grantPermission_virtualHostNoRightsBefore_succeeds() throws BrokerRemoteException, BrokerVirtualHostGrantException {
-        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.CREATED)
-                .build();
-
-        /* mock */
-        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
-                .thenReturn(mock);
-
-        /* test */
-        brokerServiceGateway.grantPermission(USER_1_USERNAME, VIRTUAL_HOST_GRANT_DTO);
-    }
-
-    @Test
-    public void grantPermission_virtualHostRightsSame_succeeds() throws BrokerRemoteException, BrokerVirtualHostGrantException {
-        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.NO_CONTENT)
-                .build();
-
-        /* mock */
-        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
-                .thenReturn(mock);
-
-        /* test */
-        brokerServiceGateway.grantPermission(USER_1_USERNAME, VIRTUAL_HOST_GRANT_DTO);
-    }
-
-    @Test
-    public void grantPermission_invalidResponseCode2_fails() {
-        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.ACCEPTED)
-                .build();
-
-        /* mock */
-        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
-                .thenReturn(mock);
-
-        /* test */
-        assertThrows(BrokerVirtualHostGrantException.class, () -> {
-            brokerServiceGateway.grantPermission(USER_1_USERNAME, VIRTUAL_HOST_GRANT_DTO);
-        });
-    }
-
-    @Test
-    public void createUser_succeeds() throws BrokerRemoteException, BrokerVirtualHostModificationException {
-        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.NO_CONTENT)
-                .build();
-
-        /* mock */
-        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
-                .thenReturn(mock);
-
-        /* test */
-        brokerServiceGateway.createUser(USER_1_USERNAME, USER_1_PASSWORD);
-    }
-
-    @Test
-    public void createUser_invalidResponseCode_fails() {
-        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.ACCEPTED)
-                .build();
-
-        /* mock */
-        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
-                .thenReturn(mock);
-
-        /* test */
-        assertThrows(BrokerVirtualHostModificationException.class, () -> {
-            brokerServiceGateway.createUser(USER_1_USERNAME, USER_1_PASSWORD);
-        });
-    }
-
-}
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/BrokerServiceGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/BrokerServiceGatewayUnitTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..96c9a6e71bc8eebf9a3e2442d2542c765330e876
--- /dev/null
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/BrokerServiceGatewayUnitTest.java
@@ -0,0 +1,416 @@
+package at.tuwien.gateway;
+
+import at.tuwien.BaseUnitTest;
+import at.tuwien.annotations.MockAmqp;
+import at.tuwien.annotations.MockOpensearch;
+import at.tuwien.api.amqp.ExchangeDto;
+import at.tuwien.api.amqp.QueueDto;
+import at.tuwien.exception.*;
+import lombok.extern.log4j.Log4j2;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestTemplate;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.*;
+
+@Log4j2
+@SpringBootTest
+@ExtendWith(SpringExtension.class)
+@MockAmqp
+@MockOpensearch
+public class BrokerServiceGatewayUnitTest extends BaseUnitTest {
+
+    @MockBean
+    @Qualifier("brokerRestTemplate")
+    private RestTemplate restTemplate;
+
+    @Autowired
+    private BrokerServiceGateway brokerServiceGateway;
+
+    @Test
+    public void createVirtualHost_succeeds() throws BrokerVirtualHostModificationException, BrokerRemoteException {
+        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.CREATED)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(mock);
+
+        /* test */
+        brokerServiceGateway.createVirtualHost(VIRTUAL_HOST_CREATE_DTO);
+    }
+
+    @Test
+    public void createVirtualHost_fails() {
+        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.NO_CONTENT)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(mock);
+
+        /* test */
+        assertThrows(BrokerVirtualHostModificationException.class, () -> {
+            brokerServiceGateway.createVirtualHost(VIRTUAL_HOST_CREATE_DTO);
+        });
+    }
+
+    @Test
+    public void createVirtualHost_unexpected_fails() {
+
+        /* mock */
+        doThrow(RestClientException.class)
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class));
+
+        /* test */
+        assertThrows(BrokerRemoteException.class, () -> {
+            brokerServiceGateway.createVirtualHost(VIRTUAL_HOST_CREATE_DTO);
+        });
+    }
+
+    @Test
+    public void grantPermission_exchangeNoRightsBefore_succeeds() throws BrokerVirtualHostGrantException, BrokerRemoteException {
+        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.CREATED)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(mock);
+
+        /* test */
+        brokerServiceGateway.grantPermission(USER_1_USERNAME, VIRTUAL_HOST_EXCHANGE_UPDATE_DTO);
+    }
+
+    @Test
+    public void grantPermission_exchangeRightsSame_succeeds() throws BrokerVirtualHostGrantException, BrokerRemoteException {
+        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.NO_CONTENT)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(mock);
+
+        /* test */
+        brokerServiceGateway.grantPermission(USER_1_USERNAME, VIRTUAL_HOST_EXCHANGE_UPDATE_DTO);
+    }
+
+    @Test
+    public void grantPermission_invalidResponseCode_fails() {
+        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.UNAUTHORIZED)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(mock);
+
+        /* test */
+        assertThrows(BrokerVirtualHostGrantException.class, () -> {
+            brokerServiceGateway.grantPermission(USER_1_USERNAME, VIRTUAL_HOST_EXCHANGE_UPDATE_DTO);
+        });
+    }
+
+    @Test
+    public void grantPermission_virtualHostNoRightsBefore_succeeds() throws BrokerRemoteException, BrokerVirtualHostGrantException {
+        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.CREATED)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(mock);
+
+        /* test */
+        brokerServiceGateway.grantPermission(USER_1_USERNAME, VIRTUAL_HOST_GRANT_DTO);
+    }
+
+    @Test
+    public void grantPermission_virtualHostRightsSame_succeeds() throws BrokerRemoteException, BrokerVirtualHostGrantException {
+        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.NO_CONTENT)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(mock);
+
+        /* test */
+        brokerServiceGateway.grantPermission(USER_1_USERNAME, VIRTUAL_HOST_GRANT_DTO);
+    }
+
+    @Test
+    public void grantPermission_invalidResponseCode2_fails() {
+        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.ACCEPTED)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(mock);
+
+        /* test */
+        assertThrows(BrokerVirtualHostGrantException.class, () -> {
+            brokerServiceGateway.grantPermission(USER_1_USERNAME, VIRTUAL_HOST_GRANT_DTO);
+        });
+    }
+
+    @Test
+    public void grantPermission_unexpected_fails() {
+
+        /* mock */
+        doThrow(RestClientException.class)
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class));
+
+        /* test */
+        assertThrows(BrokerRemoteException.class, () -> {
+            brokerServiceGateway.grantPermission(USER_1_USERNAME, VIRTUAL_HOST_GRANT_DTO);
+        });
+    }
+
+    @Test
+    public void grantPermission_unexpected2_fails() {
+
+        /* mock */
+        doThrow(RestClientException.class)
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class));
+
+        /* test */
+        assertThrows(BrokerRemoteException.class, () -> {
+            brokerServiceGateway.grantPermission(USER_1_USERNAME, VIRTUAL_HOST_EXCHANGE_UPDATE_DTO);
+        });
+    }
+
+    @Test
+    public void createUser_succeeds() throws BrokerRemoteException, BrokerVirtualHostModificationException {
+        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.NO_CONTENT)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(mock);
+
+        /* test */
+        brokerServiceGateway.createUser(USER_1_USERNAME, USER_1_PASSWORD);
+    }
+
+    @Test
+    public void createUser_invalidResponseCode_fails() {
+        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.ACCEPTED)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(mock);
+
+        /* test */
+        assertThrows(BrokerVirtualHostModificationException.class, () -> {
+            brokerServiceGateway.createUser(USER_1_USERNAME, USER_1_PASSWORD);
+        });
+    }
+
+    @Test
+    public void createUser_unexpected_fails() {
+
+        /* mock */
+        doThrow(RestClientException.class)
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class));
+
+        /* test */
+        assertThrows(BrokerRemoteException.class, () -> {
+            brokerServiceGateway.createUser(USER_1_USERNAME, USER_1_PASSWORD);
+        });
+    }
+
+    @Test
+    public void findQueue_fails() {
+        final ResponseEntity<QueueDto> mock = ResponseEntity.status(HttpStatus.NO_CONTENT)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(QueueDto.class)))
+                .thenReturn(mock);
+
+        /* test */
+        assertThrows(QueueNotFoundException.class, () -> {
+            brokerServiceGateway.findQueue("dbrepo");
+        });
+    }
+
+    @Test
+    public void findQueue_unexpected_fails() {
+
+        /* mock */
+        doThrow(RestClientException.class)
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(QueueDto.class));
+
+        /* test */
+        assertThrows(BrokerRemoteException.class, () -> {
+            brokerServiceGateway.findQueue("dbrepo");
+        });
+    }
+
+    @Test
+    public void findQueue_succeeds() throws QueueNotFoundException, BrokerRemoteException {
+        final ResponseEntity<QueueDto> mock = ResponseEntity.status(HttpStatus.OK)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(QueueDto.class)))
+                .thenReturn(mock);
+
+        /* test */
+        brokerServiceGateway.findQueue("dbrepo");
+    }
+
+    @Test
+    public void findExchange_fails() {
+        final ResponseEntity<ExchangeDto> mock = ResponseEntity.status(HttpStatus.NO_CONTENT)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(ExchangeDto.class)))
+                .thenReturn(mock);
+
+        /* test */
+        assertThrows(ExchangeNotFoundException.class, () -> {
+            brokerServiceGateway.findExchange("dbrepo");
+        });
+    }
+
+    @Test
+    public void findExchange_succeeds() throws BrokerRemoteException, ExchangeNotFoundException {
+        final ResponseEntity<ExchangeDto> mock = ResponseEntity.status(HttpStatus.OK)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(ExchangeDto.class)))
+                .thenReturn(mock);
+
+        /* test */
+        brokerServiceGateway.findExchange("dbrepo");
+    }
+
+    @Test
+    public void findExchange_unexpected_fails() {
+
+        /* mock */
+        doThrow(RestClientException.class)
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(ExchangeDto.class));
+
+        /* test */
+        assertThrows(BrokerRemoteException.class, () -> {
+            brokerServiceGateway.findExchange("dbrepo");
+        });
+    }
+
+    @Test
+    public void deleteUser_succeeds() throws BrokerRemoteException, BrokerVirtualHostModificationException {
+        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.NO_CONTENT)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(mock);
+
+        /* test */
+        brokerServiceGateway.deleteUser(USER_1_USERNAME);
+    }
+
+    @Test
+    public void deleteUser_fails() {
+        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.OK)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(mock);
+
+        /* test */
+        assertThrows(BrokerVirtualHostModificationException.class, () -> {
+            brokerServiceGateway.deleteUser(USER_1_USERNAME);
+        });
+    }
+
+    @Test
+    public void deleteUser_unexpected_fails() {
+
+        /* mock */
+        doThrow(RestClientException.class)
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class));
+
+        /* test */
+        assertThrows(BrokerRemoteException.class, () -> {
+            brokerServiceGateway.deleteUser(USER_1_USERNAME);
+        });
+    }
+
+    @Test
+    public void grantTopicPermission_succeeds() throws BrokerRemoteException, BrokerVirtualHostGrantException {
+        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.CREATED)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(mock);
+
+        /* test */
+        brokerServiceGateway.grantTopicPermission(USER_1_USERNAME, USER_1_RABBITMQ_GRANT_TOPIC_DTO);
+    }
+
+    @Test
+    public void grantTopicPermission_exists_succeeds() throws BrokerRemoteException, BrokerVirtualHostGrantException {
+        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.NO_CONTENT)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(mock);
+
+        /* test */
+        brokerServiceGateway.grantTopicPermission(USER_1_USERNAME, USER_1_RABBITMQ_GRANT_TOPIC_DTO);
+    }
+
+    @Test
+    public void grantTopicPermission_unexpected2_fails() {
+        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.BAD_GATEWAY)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(mock);
+
+        /* test */
+        assertThrows(BrokerVirtualHostGrantException.class, () -> {
+            brokerServiceGateway.grantTopicPermission(USER_1_USERNAME, USER_1_RABBITMQ_GRANT_TOPIC_DTO);
+        });
+    }
+
+    @Test
+    public void grantTopicPermission_unexpected_fails() {
+
+        /* mock */
+        doThrow(RestClientException.class)
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class));
+
+        /* test */
+        assertThrows(BrokerRemoteException.class, () -> {
+            brokerServiceGateway.grantTopicPermission(USER_1_USERNAME, USER_1_RABBITMQ_GRANT_TOPIC_DTO);
+        });
+    }
+
+}
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/CrossrefGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/CrossrefGatewayUnitTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..fb898c1c18fdf1ac475f36c0023c82e0c1c7a1bb
--- /dev/null
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/CrossrefGatewayUnitTest.java
@@ -0,0 +1,63 @@
+package at.tuwien.gateway;
+
+import at.tuwien.BaseUnitTest;
+import at.tuwien.annotations.MockAmqp;
+import at.tuwien.annotations.MockOpensearch;
+import at.tuwien.api.crossref.CrossrefDto;
+import at.tuwien.exception.DoiNotFoundException;
+import lombok.extern.log4j.Log4j2;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.web.client.ResourceAccessException;
+import org.springframework.web.client.RestTemplate;
+
+import static org.mockito.Mockito.*;
+
+@Log4j2
+@SpringBootTest
+@ExtendWith(SpringExtension.class)
+@MockAmqp
+@MockOpensearch
+public class CrossrefGatewayUnitTest extends BaseUnitTest {
+
+    @MockBean
+    @Qualifier("keycloakRestTemplate")
+    private RestTemplate restTemplate;
+
+    @Autowired
+    private CrossrefGateway crossrefGateway;
+
+    @Test
+    public void findById_succeeds() throws DoiNotFoundException {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(CrossrefDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .build());
+
+        /* test */
+        crossrefGateway.findById("501100004729");
+    }
+
+    @Test
+    public void findById_fails() throws DoiNotFoundException {
+
+        /* mock */
+        doThrow(ResourceAccessException.class)
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(CrossrefDto.class));
+
+        /* test */
+        crossrefGateway.findById("501100004729");
+    }
+
+}
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/DataDbSidecarGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/DataDbSidecarGatewayUnitTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..6a706c7e82c8077386884873a378ecb573e4e0a8
--- /dev/null
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/DataDbSidecarGatewayUnitTest.java
@@ -0,0 +1,124 @@
+package at.tuwien.gateway;
+
+import at.tuwien.BaseUnitTest;
+import at.tuwien.annotations.MockAmqp;
+import at.tuwien.annotations.MockOpensearch;
+import at.tuwien.api.keycloak.TokenDto;
+import at.tuwien.api.keycloak.UserDto;
+import at.tuwien.exception.*;
+import at.tuwien.gateway.impl.DataDbSidecarGatewayImpl;
+import at.tuwien.gateway.impl.KeycloakGatewayImpl;
+import lombok.extern.log4j.Log4j2;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.*;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.HttpServerErrorException;
+import org.springframework.web.client.ResourceAccessException;
+import org.springframework.web.client.RestTemplate;
+
+import java.nio.charset.Charset;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.*;
+
+@Log4j2
+@SpringBootTest
+@ExtendWith(SpringExtension.class)
+@MockAmqp
+@MockOpensearch
+public class DataDbSidecarGatewayUnitTest extends BaseUnitTest {
+
+    @MockBean
+    @Qualifier("sidecarRestTemplate")
+    private RestTemplate restTemplate;
+
+    @Autowired
+    private DataDbSidecarGatewayImpl dataDbSidecarGateway;
+
+    @Test
+    public void importFile_succeeds() throws DataDbSidecarException, DataProcessingException {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED)
+                        .build());
+
+        /* test */
+        dataDbSidecarGateway.importFile("data-db", 3305, "somefile.csv");
+    }
+
+    @Test
+    public void importFile_response_fails() {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT)
+                        .build());
+
+        /* test */
+        assertThrows(DataProcessingException.class, () -> {
+            dataDbSidecarGateway.importFile("data-db", 3305, "failed.csv");
+        });
+    }
+
+    @Test
+    public void importFile_unexpected_fails() {
+
+        /* mock */
+        doThrow(ResourceAccessException.class)
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class));
+
+        /* test */
+        assertThrows(DataDbSidecarException.class, () -> {
+            dataDbSidecarGateway.importFile("data-db", 3305, "failed.csv");
+        });
+    }
+
+    @Test
+    public void exportFile_succeeds() throws DataDbSidecarException, DataProcessingException {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED)
+                        .build());
+
+        /* test */
+        dataDbSidecarGateway.exportFile("data-db", 3305, "somefile.csv");
+    }
+
+    @Test
+    public void exportFile_response_fails() {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT)
+                        .build());
+
+        /* test */
+        assertThrows(DataProcessingException.class, () -> {
+            dataDbSidecarGateway.exportFile("data-db", 3305, "failed.csv");
+        });
+    }
+
+    @Test
+    public void exportFile_unexpected_fails() {
+
+        /* mock */
+        doThrow(ResourceAccessException.class)
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class));
+
+        /* test */
+        assertThrows(DataDbSidecarException.class, () -> {
+            dataDbSidecarGateway.exportFile("data-db", 3305, "failed.csv");
+        });
+    }
+
+}
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakGatewayUnitTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..b54f60a52345dc3a1d3553fc7e6aa657f16bbf58
--- /dev/null
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakGatewayUnitTest.java
@@ -0,0 +1,386 @@
+package at.tuwien.gateway;
+
+import at.tuwien.BaseUnitTest;
+import at.tuwien.annotations.MockAmqp;
+import at.tuwien.annotations.MockOpensearch;
+import at.tuwien.api.amqp.ExchangeDto;
+import at.tuwien.api.amqp.QueueDto;
+import at.tuwien.api.keycloak.TokenDto;
+import at.tuwien.api.keycloak.UserDto;
+import at.tuwien.exception.*;
+import at.tuwien.gateway.impl.KeycloakGatewayImpl;
+import lombok.extern.log4j.Log4j2;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.*;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.HttpServerErrorException;
+import org.springframework.web.client.ResourceAccessException;
+import org.springframework.web.client.RestTemplate;
+
+import java.nio.charset.Charset;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.*;
+
+@Log4j2
+@SpringBootTest
+@ExtendWith(SpringExtension.class)
+@MockAmqp
+@MockOpensearch
+public class KeycloakGatewayUnitTest extends BaseUnitTest {
+
+    @MockBean
+    @Qualifier("keycloakRestTemplate")
+    private RestTemplate restTemplate;
+
+    @Autowired
+    private KeycloakGatewayImpl keycloakGateway;
+
+    @Test
+    public void obtainToken_succeeds() throws KeycloakRemoteException, AccessDeniedException {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(TOKEN_DTO));
+
+        /* test */
+        keycloakGateway.obtainToken();
+    }
+
+    @Test
+    public void obtainToken_noAccess_fails() {
+
+        /* mock */
+        doThrow(ResourceAccessException.class)
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class));
+
+        /* test */
+        assertThrows(AccessDeniedException.class, () -> {
+            keycloakGateway.obtainToken();
+        });
+    }
+
+    @Test
+    public void obtainToken_fails() {
+
+        /* mock */
+        doThrow(HttpServerErrorException.BadGateway.create(HttpStatus.BAD_GATEWAY, "", new HttpHeaders(), new byte[]{}, Charset.defaultCharset()))
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class));
+
+        /* test */
+        assertThrows(KeycloakRemoteException.class, () -> {
+            keycloakGateway.obtainToken();
+        });
+    }
+
+    @Test
+    public void createUser_succeeds() throws KeycloakRemoteException, AccessDeniedException,
+            UserEmailAlreadyExistsException, UserAlreadyExistsException {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(TOKEN_DTO));
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.CREATED)
+                        .build());
+
+        /* test */
+        keycloakGateway.createUser(USER_1_KEYCLOAK_SIGNUP_REQUEST);
+    }
+
+    @Test
+    public void createUser_fails() {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(TOKEN_DTO));
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT)
+                        .build());
+
+        /* test */
+        assertThrows(KeycloakRemoteException.class, () -> {
+            keycloakGateway.createUser(USER_1_KEYCLOAK_SIGNUP_REQUEST);
+        });
+    }
+
+    @Test
+    public void createUser_sameEMail_fails() {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(TOKEN_DTO));
+        doThrow(HttpClientErrorException.Conflict.create(HttpStatus.CONFLICT, "same email", new HttpHeaders(), new byte[]{}, null))
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class));
+
+        /* test */
+        assertThrows(UserEmailAlreadyExistsException.class, () -> {
+            keycloakGateway.createUser(USER_1_KEYCLOAK_SIGNUP_REQUEST);
+        });
+    }
+
+    @Test
+    public void createUser_sameUsername_fails() {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(TOKEN_DTO));
+        doThrow(HttpClientErrorException.Conflict.create(HttpStatus.CONFLICT, "same username", new HttpHeaders(), new byte[]{}, null))
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class));
+
+        /* test */
+        assertThrows(UserAlreadyExistsException.class, () -> {
+            keycloakGateway.createUser(USER_1_KEYCLOAK_SIGNUP_REQUEST);
+        });
+    }
+
+    @Test
+    public void createUser_unexpected_fails() {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(TOKEN_DTO));
+        doThrow(ResourceAccessException.class)
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class));
+
+        /* test */
+        assertThrows(KeycloakRemoteException.class, () -> {
+            keycloakGateway.createUser(USER_1_KEYCLOAK_SIGNUP_REQUEST);
+        });
+    }
+
+    @Test
+    public void createUser_unexpected2_fails() {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(TOKEN_DTO));
+        doThrow(HttpServerErrorException.BadGateway.create(HttpStatus.BAD_GATEWAY, "", new HttpHeaders(), new byte[]{}, Charset.defaultCharset()))
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class));
+
+        /* test */
+        assertThrows(KeycloakRemoteException.class, () -> {
+            keycloakGateway.createUser(USER_1_KEYCLOAK_SIGNUP_REQUEST);
+        });
+    }
+
+    @Test
+    public void deleteUser_fails() {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(TOKEN_DTO));
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .build());
+
+        /* test */
+        assertThrows(KeycloakRemoteException.class, () -> {
+            keycloakGateway.deleteUser(USER_1_ID);
+        });
+    }
+
+    @Test
+    public void deleteUser_succeeds() throws UserNotFoundException, KeycloakRemoteException, AccessDeniedException {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(TOKEN_DTO));
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT)
+                        .build());
+
+        /* test */
+        keycloakGateway.deleteUser(USER_1_ID);
+    }
+
+    @Test
+    public void deleteUser_unexpected_fails() {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(TOKEN_DTO));
+        doThrow(ResourceAccessException.class)
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class));
+
+        /* test */
+        assertThrows(KeycloakRemoteException.class, () -> {
+            keycloakGateway.deleteUser(USER_1_ID);
+        });
+    }
+
+    @Test
+    public void deleteUser_notFound_fails() {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(TOKEN_DTO));
+        doThrow(HttpClientErrorException.NotFound.create(HttpStatus.NOT_FOUND, "", new HttpHeaders(), new byte[]{}, Charset.defaultCharset()))
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class));
+
+        /* test */
+        assertThrows(UserNotFoundException.class, () -> {
+            keycloakGateway.deleteUser(USER_1_ID);
+        });
+    }
+
+    @Test
+    public void deleteUser_unexpected2_fails() {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(TOKEN_DTO));
+        doThrow(HttpServerErrorException.BadGateway.create(HttpStatus.BAD_GATEWAY, "", new HttpHeaders(), new byte[]{}, Charset.defaultCharset()))
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class));
+
+        /* test */
+        assertThrows(KeycloakRemoteException.class, () -> {
+            keycloakGateway.deleteUser(USER_1_ID);
+        });
+    }
+
+    @Test
+    public void updateUserCredentials_succeeds() throws KeycloakRemoteException, AccessDeniedException {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(TOKEN_DTO));
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT)
+                        .build());
+
+        /* test */
+        keycloakGateway.updateUserCredentials(USER_1_ID, USER_1_PASSWORD_DTO);
+    }
+
+    @Test
+    public void updateUserCredentials_fails() {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(TOKEN_DTO));
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .build());
+
+        /* test */
+        assertThrows(KeycloakRemoteException.class, () -> {
+            keycloakGateway.updateUserCredentials(USER_1_ID, USER_1_PASSWORD_DTO);
+        });
+    }
+
+    @Test
+    public void updateUserCredentials_unexpected_fails() {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(TOKEN_DTO));
+        doThrow(ResourceAccessException.class)
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class));
+
+        /* test */
+        assertThrows(KeycloakRemoteException.class, () -> {
+            keycloakGateway.updateUserCredentials(USER_1_ID, USER_1_PASSWORD_DTO);
+        });
+    }
+
+    @Test
+    public void updateUserCredentials_unexpected2_fails() {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(TOKEN_DTO));
+        doThrow(HttpServerErrorException.BadGateway.create(HttpStatus.BAD_GATEWAY, "", new HttpHeaders(), new byte[]{}, Charset.defaultCharset()))
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class));
+
+        /* test */
+        assertThrows(KeycloakRemoteException.class, () -> {
+            keycloakGateway.updateUserCredentials(USER_1_ID, USER_1_PASSWORD_DTO);
+        });
+    }
+
+    @Test
+    public void findByUsername_notFound_fails() {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(TOKEN_DTO));
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(UserDto[].class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(new UserDto[]{}));
+
+        /* test */
+        assertThrows(UserNotFoundException.class, () -> {
+            keycloakGateway.findByUsername(USER_1_USERNAME);
+        });
+    }
+
+    @Test
+    public void findByUsername_remote_fails() {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(TOKEN_DTO));
+        doThrow(ResourceAccessException.class)
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(UserDto[].class));
+
+        /* test */
+        assertThrows(KeycloakRemoteException.class, () -> {
+            keycloakGateway.findByUsername(USER_1_USERNAME);
+        });
+    }
+
+    @Test
+    public void findByUsername_unexpected_fails() {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(TOKEN_DTO));
+        doThrow(HttpServerErrorException.BadGateway.create(HttpStatus.BAD_GATEWAY, "", new HttpHeaders(), new byte[]{}, Charset.defaultCharset()))
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(UserDto[].class));
+
+        /* test */
+        assertThrows(KeycloakRemoteException.class, () -> {
+            keycloakGateway.findByUsername(USER_1_USERNAME);
+        });
+    }
+
+}
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/OrcidGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/OrcidGatewayUnitTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..d6f27e21954d60cc9856ce2974adc8f48790ce39
--- /dev/null
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/OrcidGatewayUnitTest.java
@@ -0,0 +1,63 @@
+package at.tuwien.gateway;
+
+import at.tuwien.BaseUnitTest;
+import at.tuwien.annotations.MockAmqp;
+import at.tuwien.annotations.MockOpensearch;
+import at.tuwien.api.orcid.OrcidDto;
+import at.tuwien.exception.OrcidNotFoundException;
+import lombok.extern.log4j.Log4j2;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.web.client.ResourceAccessException;
+import org.springframework.web.client.RestTemplate;
+
+import static org.mockito.Mockito.*;
+
+@Log4j2
+@SpringBootTest
+@ExtendWith(SpringExtension.class)
+@MockAmqp
+@MockOpensearch
+public class OrcidGatewayUnitTest extends BaseUnitTest {
+
+    @MockBean
+    @Qualifier("keycloakRestTemplate")
+    private RestTemplate restTemplate;
+
+    @Autowired
+    private OrcidGateway orcidGateway;
+
+    @Test
+    public void findByUrl_succeeds() throws OrcidNotFoundException {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(OrcidDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .build());
+
+        /* test */
+        orcidGateway.findByUrl(USER_1_ORCID_URL);
+    }
+
+    @Test
+    public void findByUrl_fails() throws OrcidNotFoundException {
+
+        /* mock */
+        doThrow(ResourceAccessException.class)
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(OrcidDto.class));
+
+        /* test */
+        orcidGateway.findByUrl(USER_1_ORCID_URL);
+    }
+
+}
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/RorGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/RorGatewayUnitTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..29f6455ebff41a73cb354469f702685d408f5a44
--- /dev/null
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/RorGatewayUnitTest.java
@@ -0,0 +1,68 @@
+package at.tuwien.gateway;
+
+import at.tuwien.BaseUnitTest;
+import at.tuwien.annotations.MockAmqp;
+import at.tuwien.annotations.MockOpensearch;
+import at.tuwien.api.keycloak.TokenDto;
+import at.tuwien.api.keycloak.UserDto;
+import at.tuwien.api.ror.RorDto;
+import at.tuwien.exception.*;
+import at.tuwien.gateway.impl.KeycloakGatewayImpl;
+import lombok.extern.log4j.Log4j2;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.*;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.HttpServerErrorException;
+import org.springframework.web.client.ResourceAccessException;
+import org.springframework.web.client.RestTemplate;
+
+import java.nio.charset.Charset;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.*;
+
+@Log4j2
+@SpringBootTest
+@ExtendWith(SpringExtension.class)
+@MockAmqp
+@MockOpensearch
+public class RorGatewayUnitTest extends BaseUnitTest {
+
+    @MockBean
+    @Qualifier("keycloakRestTemplate")
+    private RestTemplate restTemplate;
+
+    @Autowired
+    private RorGateway rorGateway;
+
+    @Test
+    public void findById_succeeds() throws RorNotFoundException {
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(RorDto.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .build());
+
+        /* test */
+        rorGateway.findById("04d836q62");
+    }
+
+    @Test
+    public void findById_fails() throws RorNotFoundException {
+
+        /* mock */
+        doThrow(ResourceAccessException.class)
+                .when(restTemplate)
+                .exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(RorDto.class));
+
+        /* test */
+        rorGateway.findById("04d836q62");
+    }
+
+}
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java
index 91dc9c7d9ca5b69ba3f43999082b799912a1a965..6533e8a168b1f3d5174a778ad922034d9b21da69 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java
@@ -339,7 +339,7 @@ public class DatabaseServiceIntegrationTest extends BaseUnitTest {
     }
 
     @Test
-    public void obtainMetadata_tableWithoutVersioning_succeeds() throws DatabaseUnchangedException, QueryMalformedException,
+    public void obtainMetadata_tableWithoutVersioning_succeeds() throws QueryMalformedException,
             DatabaseNotFoundException, ColumnParseException {
 
         /* test */
@@ -358,8 +358,8 @@ public class DatabaseServiceIntegrationTest extends BaseUnitTest {
     }
 
     @Test
-    public void obtainMetadata_tableWithVersioning_succeeds() throws DatabaseUnchangedException, QueryMalformedException,
-            DatabaseNotFoundException, ColumnParseException {
+    public void obtainMetadata_tableWithVersioning_succeeds() throws QueryMalformedException, DatabaseNotFoundException,
+            ColumnParseException {
 
         /* test */
         final Database response = databaseService.obtainMetadata(DATABASE_1_ID);
@@ -378,8 +378,8 @@ public class DatabaseServiceIntegrationTest extends BaseUnitTest {
     }
 
     @Test
-    public void obtainMetadata_view_succeeds() throws DatabaseUnchangedException, QueryMalformedException,
-            DatabaseNotFoundException, ColumnParseException {
+    public void obtainMetadata_view_succeeds() throws QueryMalformedException, DatabaseNotFoundException,
+            ColumnParseException {
 
         /* test */
         final Database response = databaseService.obtainMetadata(DATABASE_1_ID);
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceUnitTest.java
index 3ad31da548073e7910e9c28b01725e8c78e2703f..3ab088dc73c5c6e7b945d5a03a9013e5958c60c5 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceUnitTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceUnitTest.java
@@ -5,12 +5,10 @@ import at.tuwien.annotations.MockAmqp;
 import at.tuwien.annotations.MockOpensearch;
 import at.tuwien.api.database.query.QueryDto;
 import at.tuwien.api.identifier.BibliographyTypeDto;
-import at.tuwien.entities.database.Database;
 import at.tuwien.entities.identifier.Creator;
 import at.tuwien.entities.identifier.Identifier;
 import at.tuwien.entities.identifier.NameIdentifierSchemeType;
 import at.tuwien.exception.*;
-import at.tuwien.repository.mdb.DatabaseRepository;
 import at.tuwien.repository.mdb.IdentifierRepository;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -42,9 +40,6 @@ public class IdentifierServiceUnitTest extends BaseUnitTest {
     @MockBean
     private IdentifierRepository identifierRepository;
 
-    @MockBean
-    private DatabaseRepository databaseRepository;
-
     @MockBean
     private DatabaseService databaseService;
 
@@ -176,11 +171,9 @@ public class IdentifierServiceUnitTest extends BaseUnitTest {
     }
 
     @Test
-    public void create_database_succeeds()
-            throws DatabaseNotFoundException, UserNotFoundException, IdentifierAlreadyExistsException,
-            QueryNotFoundException, IdentifierPublishingNotAllowedException, RemoteUnavailableException,
-            IdentifierRequestException, ViewNotFoundException, QueryStoreException, DatabaseConnectionException,
-            ImageNotSupportedException, IdentifierNotFoundException {
+    public void create_database_succeeds() throws UserNotFoundException, QueryStoreException,
+            QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException, RemoteUnavailableException,
+            IdentifierRequestException, ViewNotFoundException {
 
         /* mock */
         when(databaseService.find(DATABASE_1_ID))
@@ -198,10 +191,9 @@ public class IdentifierServiceUnitTest extends BaseUnitTest {
     }
 
     @Test
-    public void create_existsSubset_succeeds() throws DatabaseNotFoundException, UserNotFoundException,
-            QueryStoreException, DatabaseConnectionException, QueryNotFoundException, ImageNotSupportedException,
-            IdentifierAlreadyExistsException, IdentifierPublishingNotAllowedException, RemoteUnavailableException,
-            IdentifierNotFoundException, IdentifierRequestException, ViewNotFoundException {
+    public void create_existsSubset_succeeds() throws UserNotFoundException, QueryStoreException,
+            QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException, RemoteUnavailableException,
+            IdentifierRequestException, ViewNotFoundException {
 
         /* mock */
         when(databaseService.find(DATABASE_2_ID))
@@ -217,10 +209,9 @@ public class IdentifierServiceUnitTest extends BaseUnitTest {
     }
 
     @Test
-    public void create_existsDatabase_succeeds() throws DatabaseNotFoundException, IdentifierAlreadyExistsException,
-            UserNotFoundException, QueryStoreException, DatabaseConnectionException, QueryNotFoundException,
-            ImageNotSupportedException, IdentifierPublishingNotAllowedException, RemoteUnavailableException,
-            IdentifierNotFoundException, IdentifierRequestException, ViewNotFoundException {
+    public void create_existsDatabase_succeeds() throws UserNotFoundException, QueryStoreException,
+            QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException, RemoteUnavailableException,
+            IdentifierRequestException, ViewNotFoundException {
 
         /* mock */
         when(databaseService.find(DATABASE_1_ID))
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java
index 5730ee743b70b58ce83f388f7924465c37f86ff1..4d3988a88d39fe257532c0bf0694cec08aa53e2d 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java
@@ -5,7 +5,9 @@ import at.tuwien.ExportResource;
 import at.tuwien.annotations.MockAmqp;
 import at.tuwien.annotations.MockOpensearch;
 import at.tuwien.api.database.query.ExecuteStatementDto;
+import at.tuwien.api.database.query.ImportDto;
 import at.tuwien.api.database.query.QueryResultDto;
+import at.tuwien.api.database.table.TableCsvDeleteDto;
 import at.tuwien.api.database.table.TableCsvDto;
 import at.tuwien.config.MariaDbConfig;
 import at.tuwien.config.MariaDbContainerConfig;
@@ -17,6 +19,7 @@ import at.tuwien.repository.mdb.*;
 import at.tuwien.service.impl.QueryServiceImpl;
 import lombok.SneakyThrows;
 import lombok.extern.log4j.Log4j2;
+import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -35,6 +38,7 @@ import org.testcontainers.containers.MinIOContainer;
 import org.testcontainers.junit.jupiter.Container;
 import org.testcontainers.junit.jupiter.Testcontainers;
 
+import java.io.File;
 import java.io.IOException;
 import java.math.BigInteger;
 import java.sql.SQLException;
@@ -180,6 +184,24 @@ public class QueryServiceIntegrationTest extends BaseUnitTest {
         });
     }
 
+    @Test
+    public void insert_csv_succeeds() throws IOException, TableNotFoundException, TableMalformedException,
+            DatabaseNotFoundException, DataProcessingException {
+        final String filename = RandomStringUtils.randomAlphabetic(40) + ".csv";
+        final ImportDto request = ImportDto.builder()
+                .quote('"')
+                .nullElement("NA")
+                .separator(';')
+                .location(filename)
+                .build();
+
+        /* mock */
+        FileUtils.copyFile(new File("./src/test/resources/csv/weather_aus.csv"), new File("/tmp/" + filename));
+
+        /* test */
+        queryService.insert(DATABASE_1_ID, TABLE_1_ID, request, USER_1_PRINCIPAL);
+    }
+
     @Test
     public void insert_date_succeeds() throws TableNotFoundException, TableMalformedException, SQLException,
             DatabaseNotFoundException {
@@ -517,7 +539,7 @@ public class QueryServiceIntegrationTest extends BaseUnitTest {
     @Test
     public void findOne_emptySet_succeeds() throws DatabaseNotFoundException, ImageNotSupportedException,
             QueryMalformedException, QueryStoreException, QueryNotFoundException, FileStorageException, SQLException,
-            IOException {
+            IOException, DataProcessingException {
         final String filename = RandomStringUtils.randomAlphabetic(40) + ".csv";
         final Query query = Query.builder()
                 .id(QUERY_1_ID)
@@ -545,6 +567,28 @@ public class QueryServiceIntegrationTest extends BaseUnitTest {
         assertNotNull(response.getResource());
     }
 
+    @Test
+    public void delete_emptyKeySet_succeeds() throws TableNotFoundException, TableMalformedException, QueryMalformedException,
+            DatabaseNotFoundException, ImageNotSupportedException {
+        final TableCsvDeleteDto request = TableCsvDeleteDto.builder()
+                .keys(Map.of())
+                .build();
+
+        /* test */
+        queryService.delete(DATABASE_1_ID, TABLE_1_ID, request, USER_1_PRINCIPAL);
+    }
+
+    @Test
+    public void delete_succeeds() throws TableNotFoundException, TableMalformedException, QueryMalformedException,
+            DatabaseNotFoundException, ImageNotSupportedException {
+        final TableCsvDeleteDto request = TableCsvDeleteDto.builder()
+                .keys(Map.of("id", "1"))
+                .build();
+
+        /* test */
+        queryService.delete(DATABASE_1_ID, TABLE_1_ID, request, USER_1_PRINCIPAL);
+    }
+
     @SneakyThrows
     private static Instant toInstant(String str) {
         final DateTimeFormatter formatter = new DateTimeFormatterBuilder()
diff --git a/dbrepo-metadata-service/rest-service/src/test/resources/csv/weather_aus.csv b/dbrepo-metadata-service/rest-service/src/test/resources/csv/weather_aus.csv
new file mode 100644
index 0000000000000000000000000000000000000000..f1c02b05a665f99e7662d44895610112104e8366
--- /dev/null
+++ b/dbrepo-metadata-service/rest-service/src/test/resources/csv/weather_aus.csv
@@ -0,0 +1 @@
+4;"2024-01-27";"Vienna";NA;NA
\ No newline at end of file
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/BrokerServiceGateway.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/BrokerServiceGateway.java
index 370c627901ce38693d0cd833b8bcd3446cb7a42f..8b07b0e6e40f7f4d140330b65683a4ff85c23636 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/BrokerServiceGateway.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/BrokerServiceGateway.java
@@ -18,14 +18,6 @@ public interface BrokerServiceGateway {
     void grantTopicPermission(String username, GrantExchangePermissionsDto data) throws BrokerRemoteException,
             BrokerVirtualHostGrantException;
 
-    /**
-     * Finds all active consumers on the virtual host "dbrepo".
-     *
-     * @return The list of active consumers.
-     * @throws BrokerRemoteException The Broker Service did not respond within the 3s timeout.
-     */
-    List<ConsumerDto> findAllConsumers() throws BrokerRemoteException;
-
     /**
      * Create virtual host at the queue service.
      *
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/CrossrefGateway.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/CrossrefGateway.java
index 30bc0dc73dcc793621fc9be7a96a674a17be2a35..58e023ac9d32c3e1820969b1c73478a4d141de9d 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/CrossrefGateway.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/CrossrefGateway.java
@@ -4,5 +4,13 @@ import at.tuwien.api.crossref.CrossrefDto;
 import at.tuwien.exception.DoiNotFoundException;
 
 public interface CrossrefGateway {
+
+    /**
+     * Retrieves metadata from the CrossRef funder database for a given CrossRef id.
+     *
+     * @param id The CrossRef id.
+     * @return The CrossRef metadata from the CrossRef funder database.
+     * @throws DoiNotFoundException The metadata was not found in the CrossRef funder database.
+     */
     CrossrefDto findById(String id) throws DoiNotFoundException;
 }
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataDbSidecarGateway.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataDbSidecarGateway.java
index c7dff9c9e3e8d340fbfb490398e772f51881ef67..a8eae9032a9504306448521c87f86c76bad9104a 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataDbSidecarGateway.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataDbSidecarGateway.java
@@ -1,9 +1,10 @@
 package at.tuwien.gateway;
 
 import at.tuwien.exception.DataDbSidecarException;
+import at.tuwien.exception.DataProcessingException;
 
 public interface DataDbSidecarGateway {
-    void importFile(String hostname, Integer port, String filename) throws DataDbSidecarException;
+    void importFile(String hostname, Integer port, String filename) throws DataDbSidecarException, DataProcessingException;
 
-    void exportFile(String hostname, Integer port, String filename) throws DataDbSidecarException;
+    void exportFile(String hostname, Integer port, String filename) throws DataDbSidecarException, DataProcessingException;
 }
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/RorGateway.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/RorGateway.java
index 29f226efe7ec5f3da50ba21ff47297b27dd49ae5..27603b99191708e22970c7452fc6a44337809128 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/RorGateway.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/RorGateway.java
@@ -5,5 +5,12 @@ import at.tuwien.exception.RorNotFoundException;
 
 public interface RorGateway {
 
+    /**
+     * Retrieves metadata from the ROR database for an organizational ROR id.
+     *
+     * @param id The ROR id.
+     * @return The metadata from the ROR database, if successful.
+     * @throws RorNotFoundException The ROR id was not found in the ROR database.
+     */
     RorDto findById(String id) throws RorNotFoundException;
 }
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java
index 018c66c2b3637b3e2a587da409a1bb459b3d3386..3d674e41f4ac44469f8a00e71f359979feb2a757 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java
@@ -102,7 +102,7 @@ public class BrokerServiceGatewayImpl implements BrokerServiceGateway {
             response = restTemplate.exchange(url, HttpMethod.DELETE, new HttpEntity<>(null), Void.class);
         } catch (Exception e) {
             log.error("Failed to delete user: remote host answered unexpected: {}", e.getMessage());
-            throw new BrokerRemoteException("Failed to delete user: remote host answered unexpected", e);
+            throw new BrokerRemoteException("Failed to delete user: remote host answered unexpected: " + e.getMessage(), e);
         }
         if (!response.getStatusCode().equals(HttpStatus.NO_CONTENT)) {
             log.error("Failed to delete user: {}", response.getStatusCode());
@@ -124,8 +124,8 @@ public class BrokerServiceGatewayImpl implements BrokerServiceGateway {
             throw new BrokerRemoteException("Failed to create permissions: remote host answered unexpected", e);
         }
         if (!response.getStatusCode().equals(HttpStatus.CREATED) && !response.getStatusCode().equals(HttpStatus.NO_CONTENT)) {
-            log.error("Failed to grant virtual host permissions: {}", response.getStatusCode());
-            throw new BrokerVirtualHostGrantException("Failed to grant virtual host permissions");
+            log.error("Failed to grant virtual host permissions at broker service");
+            throw new BrokerVirtualHostGrantException("Failed to grant virtual host permissions at broker service");
         }
         log.trace("Grant virtual host permissions for user with username {}", username);
     }
@@ -143,29 +143,12 @@ public class BrokerServiceGatewayImpl implements BrokerServiceGateway {
             throw new BrokerRemoteException("Failed to grant topic permissions: remote host answered unexpected", e);
         }
         if (!response.getStatusCode().equals(HttpStatus.CREATED) && !response.getStatusCode().equals(HttpStatus.NO_CONTENT)) {
-            log.error("Failed to grant topic permissions: {}", response.getStatusCode());
-            throw new BrokerVirtualHostGrantException("Failed to grant topic permissions");
+            log.error("Failed to grant topic permissions at broker service");
+            throw new BrokerVirtualHostGrantException("Failed to grant topic permissions at broker service");
         }
         log.trace("Grant topic permissions for user with username {}", username);
     }
 
-    @Override
-    public List<ConsumerDto> findAllConsumers() throws BrokerRemoteException {
-        final String url = "/api/consumers/" + rabbitConfig.getVirtualHost();
-        log.trace("gateway broker find all consumers, virtual host={}", rabbitConfig.getVirtualHost());
-        log.debug("find consumers from url {}{}", gatewayConfig.getBrokerEndpoint(), url);
-        final ResponseEntity<List<ConsumerDto>> response;
-        try {
-            response = restTemplate.exchange(URI.create(url), HttpMethod.GET, HttpEntity.EMPTY,
-                    new ParameterizedTypeReference<>() {
-                    });
-        } catch (Exception e) {
-            log.error("Failed to find consumers: remote host answered unexpected: {}", e.getMessage());
-            throw new BrokerRemoteException("Failed to find consumers: remote host answered unexpected", e);
-        }
-        return response.getBody();
-    }
-
     @Override
     public QueueDto findQueue(String name) throws BrokerRemoteException, QueueNotFoundException {
         final String url = "/api/queues/" + rabbitConfig.getVirtualHost() + "/" + name;
@@ -181,8 +164,8 @@ public class BrokerServiceGatewayImpl implements BrokerServiceGateway {
             throw new BrokerRemoteException("Failed to find queue: remote host answered unexpected", e);
         }
         if (!response.getStatusCode().equals(HttpStatus.OK)) {
-            log.error("Failed find queue: {}", response.getStatusCode());
-            throw new QueueNotFoundException("Failed to find queue");
+            log.error("Failed find queue at broker service");
+            throw new QueueNotFoundException("Failed to find queue at broker service");
         }
         return response.getBody();
     }
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataDbSidecarGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataDbSidecarGatewayImpl.java
index 6e4b2b56be874c1387d408f872a39158d732a086..5a793ed008b27240b1b804e74b0c3a803708578c 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataDbSidecarGatewayImpl.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataDbSidecarGatewayImpl.java
@@ -1,12 +1,11 @@
 package at.tuwien.gateway.impl;
 
 import at.tuwien.exception.DataDbSidecarException;
+import at.tuwien.exception.DataProcessingException;
 import at.tuwien.gateway.DataDbSidecarGateway;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpMethod;
+import org.springframework.http.*;
 import org.springframework.stereotype.Service;
 import org.springframework.web.client.HttpServerErrorException;
 import org.springframework.web.client.ResourceAccessException;
@@ -23,26 +22,39 @@ public class DataDbSidecarGatewayImpl implements DataDbSidecarGateway {
     }
 
     @Override
-    public void importFile(String hostname, Integer port, String filename) throws DataDbSidecarException {
+    public void importFile(String hostname, Integer port, String filename) throws DataDbSidecarException,
+            DataProcessingException {
         final HttpHeaders headers = new HttpHeaders();
         headers.set("Accept", "application/json");
+        final ResponseEntity<Void> response;
         try {
-            restTemplate.exchange("http://" + hostname + ":" + port + "/sidecar/import/" + filename, HttpMethod.POST, new HttpEntity<>(null, headers), Void.class);
+            response = restTemplate.exchange("http://" + hostname + ":" + port + "/sidecar/import/" + filename,
+                    HttpMethod.POST, new HttpEntity<>(null, headers), Void.class);
         } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) {
             log.error("Failed to import .csv in data-db sidecar: {}", e.getMessage());
-            throw new DataDbSidecarException("Failed to import .csv in data-db sidecar: " + e.getMessage());
+            throw new DataDbSidecarException("Failed to import .csv in data-db sidecar: " + e.getMessage(), e);
+        }
+        if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) {
+            log.error("Failed to import .csv in data-db sidecar");
+            throw new DataProcessingException("Failed to import .csv in data-db sidecar");
         }
     }
 
     @Override
-    public void exportFile(String hostname, Integer port, String filename) throws DataDbSidecarException {
+    public void exportFile(String hostname, Integer port, String filename) throws DataDbSidecarException, DataProcessingException {
         final HttpHeaders headers = new HttpHeaders();
         headers.set("Accept", "application/json");
+        final ResponseEntity<Void> response;
         try {
-            restTemplate.exchange("http://" + hostname + ":" + port + "/sidecar/export/" + filename, HttpMethod.POST, new HttpEntity<>(null, headers), Void.class);
+            response = restTemplate.exchange("http://" + hostname + ":" + port + "/sidecar/export/" + filename,
+                    HttpMethod.POST, new HttpEntity<>(null, headers), Void.class);
         } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) {
             log.error("Failed to export .csv in data-db sidecar: {}", e.getMessage());
-            throw new DataDbSidecarException("Failed to export .csv in data-db sidecar: " + e.getMessage());
+            throw new DataDbSidecarException("Failed to export .csv in data-db sidecar: " + e.getMessage(), e);
+        }
+        if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) {
+            log.error("Failed to export .csv in data-db sidecar");
+            throw new DataProcessingException("Failed to export .csv in data-db sidecar");
         }
     }
 }
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java
index 6f29d138ffb858c526e1e18b0f76c0d27cb5d99c..fbf2c7b2518bf23d1b3f96b33628459b87b0dd94 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java
@@ -51,7 +51,7 @@ public class KeycloakGatewayImpl implements KeycloakGateway {
             throw new AccessDeniedException("Failed to obtain admin token: " + e.getMessage());
         } catch (Exception e) {
             log.error("Failed to create user: remote host answered unexpected: {}", e.getMessage());
-            throw new KeycloakRemoteException("Failed to create user: remote host answered unexpected", e);
+            throw new KeycloakRemoteException("Failed to create user: remote host answered unexpected: " + e.getMessage(), e);
         }
         return response.getBody();
     }
@@ -81,7 +81,7 @@ public class KeycloakGatewayImpl implements KeycloakGateway {
             }
         } catch (Exception e) {
             log.error("Failed to create user: remote host answered unexpected: {}", e.getMessage());
-            throw new KeycloakRemoteException("Failed to create user: remote host answered unexpected", e);
+            throw new KeycloakRemoteException("Failed to create user: remote host answered unexpected: " + e.getMessage(), e);
         }
         if (!response.getStatusCode().equals(HttpStatus.CREATED)) {
             log.error("Failed to create user: status {} was not expected", response.getStatusCode().value());
@@ -162,7 +162,7 @@ public class KeycloakGatewayImpl implements KeycloakGateway {
             throw new KeycloakRemoteException("Failed to find user: " + e.getMessage());
         } catch (Exception e) {
             log.error("Failed to create user: remote host answered unexpected: {}", e.getMessage());
-            throw new KeycloakRemoteException("Failed to create user: remote host answered unexpected", e);
+            throw new KeycloakRemoteException("Failed to create user: remote host answered unexpected: " + e.getMessage(), e);
         }
         final UserDto[] body = response.getBody();
         if (body == null || body.length != 1) {
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/RorGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/RorGatewayImpl.java
index cf1600aea5bc8f6fb65ac85495eb3a2520a51dc3..6eeb74c3c072f684834f90228dd755bfcb959c09 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/RorGatewayImpl.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/RorGatewayImpl.java
@@ -34,7 +34,7 @@ public class RorGatewayImpl implements RorGateway {
             response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null, headers), RorDto.class);
         } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) {
             log.error("Failed to retrieve ROR metadata from URL {}: {}", url, e.getMessage());
-            throw new RorNotFoundException("Failed to retrieve ROR metadata from URL " + url + ": " + e.getMessage());
+            throw new RorNotFoundException("Failed to retrieve ROR metadata from URL " + url + ": " + e.getMessage(), e);
         }
         return response.getBody();
     }
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/IdentifierService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/IdentifierService.java
index 4a3032281a1de86dcc165450b474c3d89dadd066..457b9dc3e8489cfccc59901b2530805004afcf23 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/IdentifierService.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/IdentifierService.java
@@ -141,7 +141,7 @@ public interface IdentifierService {
      */
     InputStreamResource exportResource(Long identifierId, Principal principal) throws IdentifierNotFoundException,
             QueryNotFoundException, IdentifierRequestException, QueryStoreException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException, DataDbSidecarException;
+            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException, DataDbSidecarException, DataProcessingException;
 
     /**
      * Soft-deletes an identifier for a given id in the metadata database. Does not actually remove the entity from the
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/QueryService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/QueryService.java
index 738eddb4a6d110341d364ec3da8c93f896d0aff3..d6350915820967217193eeceffae6a359a16484b 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/QueryService.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/QueryService.java
@@ -125,7 +125,7 @@ public interface QueryService {
      */
     ExportResource tableFindAll(Long databaseId, Long tableId, Instant timestamp, Principal principal)
             throws TableNotFoundException, DatabaseNotFoundException, FileStorageException, QueryMalformedException,
-            DataDbSidecarException;
+            DataDbSidecarException, DataProcessingException;
 
     /**
      * Select all data known in the view id tuple and return a page of specific size.
@@ -161,7 +161,7 @@ public interface QueryService {
      */
     ExportResource findOne(Long databaseId, Long queryId, Principal principal) throws DatabaseNotFoundException,
             ImageNotSupportedException, FileStorageException, QueryStoreException, QueryNotFoundException,
-            QueryMalformedException, DataDbSidecarException;
+            QueryMalformedException, DataDbSidecarException, DataProcessingException;
 
     /**
      * Count the total tuples for a given table id within a database id at a given time.
@@ -242,5 +242,5 @@ public interface QueryService {
      * @throws DataDbSidecarException    The data database sidecar failed to import the dataset.
      */
     void insert(Long databaseId, Long tableId, ImportDto data, Principal principal) throws TableMalformedException,
-            DatabaseNotFoundException, TableNotFoundException, DataDbSidecarException;
+            DatabaseNotFoundException, TableNotFoundException, DataDbSidecarException, DataProcessingException;
 }
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DataCiteIdentifierServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DataCiteIdentifierServiceImpl.java
index 3dfa60dc757343d49bd197c747e9831faa4c0d44..541e1fee8a3b9033738838b2cb6991531d31b3cf 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DataCiteIdentifierServiceImpl.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DataCiteIdentifierServiceImpl.java
@@ -189,7 +189,7 @@ public class DataCiteIdentifierServiceImpl implements IdentifierService {
     public InputStreamResource exportResource(Long identifierId, Principal principal)
             throws IdentifierNotFoundException, QueryNotFoundException, FileStorageException,
             IdentifierRequestException, QueryStoreException, QueryMalformedException, DatabaseNotFoundException,
-            ImageNotSupportedException, DataDbSidecarException {
+            ImageNotSupportedException, DataDbSidecarException, DataProcessingException {
         return identifierService.exportResource(identifierId, principal);
     }
 
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java
index 7c02d46a2dba4181aa185b8ef101c010c6917bca..528280b1a74b1da6950a3a312b0fb79dc0b3b6d6 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java
@@ -245,7 +245,8 @@ public class IdentifierServiceImpl implements IdentifierService {
     @Transactional(readOnly = true)
     public InputStreamResource exportResource(Long identifierId, Principal principal) throws IdentifierNotFoundException,
             QueryNotFoundException, IdentifierRequestException, QueryStoreException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException, DataDbSidecarException {
+            DatabaseNotFoundException, ImageNotSupportedException, FileStorageException, DataDbSidecarException,
+            DataProcessingException {
         /* check */
         final Identifier identifier = find(identifierId);
         if (identifier.getType().equals(IdentifierType.DATABASE)) {
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/MariaDbServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/MariaDbServiceImpl.java
index 07df2b4ca5950d5f3dbbb60c8e68746044b919f6..626cbc38d35bd9b19a015bf3b75dc03b74157237 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/MariaDbServiceImpl.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/MariaDbServiceImpl.java
@@ -36,6 +36,7 @@ import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.*;
+import java.util.function.UnaryOperator;
 
 @Log4j2
 @Service
@@ -216,31 +217,47 @@ public class MariaDbServiceImpl extends HibernateConnector implements DatabaseSe
     @Override
     @Transactional
     public Database obtainMetadata(Long databaseId) throws DatabaseNotFoundException, QueryMalformedException,
-            DatabaseUnchangedException, ColumnParseException {
+            ColumnParseException {
         /* check */
         final Database database = findById(databaseId);
         final List<Table> diffTables;
+        final List<Table> knownTables;
         final List<View> diffViews;
         final ComboPooledDataSource dataSource = getPrivilegedDataSource(database.getContainer().getImage(), database.getContainer(), database);
         try {
             final Connection connection = dataSource.getConnection();
             final PreparedStatement preparedStatement0 = databaseMapper.databaseToDatabaseMetadata(connection, database);
-            diffTables = tableMapper.resultListToTableList(preparedStatement0.executeQuery(), database)
-                    .stream()
-                    .filter(table -> database.getTables()
+            final List<Table> tables = tableMapper.resultListToTableList(preparedStatement0.executeQuery(), database);
+            diffTables = tables.stream()
+                    .filter(obtainedTable -> database.getTables()
                             .stream()
+                            .noneMatch(t -> t.getInternalName().equals(obtainedTable.getInternalName())))
+                    .toList();
+            knownTables = tables.stream()
+                    .filter(table -> diffTables.stream()
                             .noneMatch(t -> t.getInternalName().equals(table.getInternalName())))
+                    .map(obtainedTable -> {
+                        final Optional<Table> optional = database.getTables()
+                                .stream()
+                                .filter(t -> t.getInternalName().equals(obtainedTable.getInternalName()))
+                                .findFirst();
+                        if (optional.isPresent()) {
+                            final Table table = optional.get();
+                            table.setNumRows(obtainedTable.getNumRows());
+                            table.setDataLength(obtainedTable.getDataLength());
+                            table.setMaxDataLength(obtainedTable.getMaxDataLength());
+                            table.setAvgRowLength(obtainedTable.getAvgRowLength());
+                            return table;
+                        }
+                        return obtainedTable;
+                    })
                     .toList();
-            diffViews = tableMapper.resultListToViewList(preparedStatement0.executeQuery(), database)
-                    .stream()
+            final List<View> views = tableMapper.resultListToViewList(preparedStatement0.executeQuery(), database);
+            diffViews = views.stream()
                     .filter(view -> database.getViews()
                             .stream()
                             .noneMatch(v -> v.getInternalName().equals(view.getInternalName())))
                     .toList();
-            if (diffTables.isEmpty() && diffViews.isEmpty()) {
-                log.debug("database with id {} does not contain any unknown tables and any unknown views", databaseId);
-                throw new DatabaseUnchangedException("Database with id " + databaseId + " does not contain any unknown tables and any unknown views");
-            }
             /* default times */
             final Optional<ContainerImageDate> defaultDateFormat = containerRepository.findDefaultDateFormat();
             if (defaultDateFormat.isEmpty()) {
@@ -255,6 +272,16 @@ public class MariaDbServiceImpl extends HibernateConnector implements DatabaseSe
             /* obtain table schema */
             log.info("Database with id {} contains {} unknown table(s) and {} unknown view(s)", databaseId, diffTables.size(), diffViews.size());
             log.debug("database with id {} misses table(s) in metadata database: {}", databaseId, diffTables.stream().map(Table::getInternalName).toList());
+            database.getTables().replaceAll(table -> {
+                final Optional<Table> optional = knownTables.stream()
+                        .filter(t -> t.getId().equals(table.getId()))
+                        .findFirst();
+                if (optional.isPresent()) {
+                    log.trace("found table with id {} and merged it", table.getId());
+                    return optional.get();
+                }
+                return table;
+            });
             for (Table table : diffTables) {
                 final PreparedStatement preparedStatement1 = queryMapper.obtainTableMetadataRawQuery(connection, table.getDatabase().getInternalName(), table.getInternalName());
                 table = tableMapper.resultSetTableToObtainedMetadata(preparedStatement1.executeQuery(), table,
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java
index b78715ee47068b3c4956e92a8ca562c792fe3ab1..94b66158f2b284fcd1a11f92c70fa584bf058d13 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java
@@ -242,7 +242,7 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService
     @Transactional(readOnly = true)
     public ExportResource tableFindAll(Long databaseId, Long tableId, Instant timestamp, Principal principal)
             throws TableNotFoundException, DatabaseNotFoundException, FileStorageException, QueryMalformedException,
-            DataDbSidecarException {
+            DataDbSidecarException, DataProcessingException {
         final String filename = RandomStringUtils.randomAlphabetic(40) + ".csv";
         /* find */
         final Database database = databaseService.find(databaseId);
@@ -264,7 +264,7 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService
     }
 
     private ExportResource retrieveBlobAsResource(Container container, String filename) throws DataDbSidecarException,
-            FileStorageException {
+            FileStorageException, DataProcessingException {
         /* upload from sidecar into blob storage */
         dataDbSidecarGateway.exportFile(container.getSidecarHost(), container.getSidecarPort(), filename);
         /* export file from blob storage */
@@ -287,14 +287,14 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService
     @Transactional(readOnly = true)
     public ExportResource findOne(Long databaseId, Long queryId, Principal principal)
             throws DatabaseNotFoundException, ImageNotSupportedException, FileStorageException, QueryStoreException,
-            QueryNotFoundException, QueryMalformedException, DataDbSidecarException {
+            QueryNotFoundException, QueryMalformedException, DataDbSidecarException, DataProcessingException {
         return findOne(databaseId, queryId, principal, RandomStringUtils.randomAlphabetic(40) + ".csv");
     }
 
     @Transactional(readOnly = true)
     public ExportResource findOne(Long databaseId, Long queryId, Principal principal, String filename)
             throws DatabaseNotFoundException, ImageNotSupportedException, FileStorageException, QueryStoreException,
-            QueryNotFoundException, QueryMalformedException, DataDbSidecarException {
+            QueryNotFoundException, QueryMalformedException, DataDbSidecarException, DataProcessingException {
         /* find */
         final Database database = databaseService.find(databaseId);
         final Query query = storeService.findOne(databaseId, queryId, principal);
@@ -372,7 +372,8 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService
     @Override
     @Transactional
     public void insert(Long databaseId, Long tableId, ImportDto data, Principal principal)
-            throws TableMalformedException, DatabaseNotFoundException, TableNotFoundException, DataDbSidecarException {
+            throws TableMalformedException, DatabaseNotFoundException, TableNotFoundException, DataDbSidecarException,
+            DataProcessingException {
         /* find */
         final Database database = databaseService.find(databaseId);
         final Table table = tableService.find(databaseId, tableId);
diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java
index 43194d7daf641478bb1c9d9bcf714ade9f0cb4d8..3342e7939d2a419d91586cd2b6a818f9a3273a88 100644
--- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java
+++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java
@@ -24,6 +24,7 @@ import at.tuwien.api.database.table.constraints.unique.UniqueDto;
 import at.tuwien.api.identifier.*;
 import at.tuwien.api.keycloak.CredentialDto;
 import at.tuwien.api.keycloak.CredentialTypeDto;
+import at.tuwien.api.keycloak.TokenDto;
 import at.tuwien.api.keycloak.UserCreateDto;
 import at.tuwien.api.maintenance.BannerMessageCreateDto;
 import at.tuwien.api.maintenance.BannerMessageTypeDto;
@@ -229,6 +230,11 @@ public abstract class BaseTest {
     public final static String ROLE_DEFAULT_RESEARCHER_ROLES_NAME = "default-researcher-roles";
     public final static UUID ROLE_DEFAULT_RESEARCHER_ROLES_REALM_ID = REALM_DBREPO_ID;
 
+    public final static TokenDto TOKEN_DTO = TokenDto.builder()
+            .accessToken("ey.yee.skrr")
+            .scope("openid")
+            .build();
+
     public final static String USER_BROKER_USERNAME = "guest";
     public final static String USER_BROKER_PASSWORD = "guest";
 
diff --git a/dbrepo-search-db/init/indices/database.json b/dbrepo-search-db/init/indices/database.json
index 35be7c5ae43bafe791adc58b90023287e7160402..fedeae2384d124803048ccc602b9cc45966e47b4 100644
--- a/dbrepo-search-db/init/indices/database.json
+++ b/dbrepo-search-db/init/indices/database.json
@@ -583,6 +583,9 @@
       "tables": {
         "type": "object",
         "properties": {
+          "avg_row_length": {
+            "type": "long"
+          },
           "columns": {
             "properties": {
               "auto_generated": {
@@ -724,6 +727,9 @@
           "database_id": {
             "type": "keyword"
           },
+          "data_length": {
+            "type": "long"
+          },
           "description": {
             "type": "text"
           },
@@ -939,6 +945,12 @@
           "name": {
             "type": "keyword"
           },
+          "num_rows": {
+            "type": "long"
+          },
+          "max_data_length": {
+            "type": "long"
+          },
           "owner": {
             "type": "object",
             "properties": {
diff --git a/dbrepo-ui/pages/database/_database_id/info.vue b/dbrepo-ui/pages/database/_database_id/info.vue
index 284395ed0e7e5aa39bdec7363ee80b16ba085c97..bfacf06b0a491abd7be02ed9273be0f789df9896 100644
--- a/dbrepo-ui/pages/database/_database_id/info.vue
+++ b/dbrepo-ui/pages/database/_database_id/info.vue
@@ -16,10 +16,6 @@
             <v-list dense>
               <v-list-item>
                 <v-list-item-content>
-                  <v-list-item-title>
-                    Database Visibility
-                  </v-list-item-title>
-                  <v-list-item-content v-if="database" v-text="`${database.is_public ? 'Public' : 'Private'}`" />
                   <v-list-item-title class="mt-2">
                     Database Name
                   </v-list-item-title>
@@ -28,6 +24,14 @@
                     Database Internal Name
                   </v-list-item-title>
                   <v-list-item-content v-if="database" v-text="database.internal_name" />
+                  <v-list-item-title>
+                    Database Visibility
+                  </v-list-item-title>
+                  <v-list-item-content v-if="database" v-text="`${database.is_public ? 'Public' : 'Private'}`" />
+                  <v-list-item-title>
+                    Database Size
+                  </v-list-item-title>
+                  <v-list-item-content v-if="databaseSize" v-text="databaseSize" />
                   <v-list-item-title class="mt-2">
                     Database Owner
                   </v-list-item-title>
@@ -102,7 +106,7 @@
 
 <script>
 import DatabaseToolbar from '@/components/database/DatabaseToolbar.vue'
-import { formatTimestampUTCLabel } from '@/utils'
+import { formatTimestampUTCLabel, sizeToHumanLabel } from '@/utils'
 import DatabaseMapper from '@/api/database.mapper'
 import Summary from '@/components/identifier/Summary'
 import Select from '@/components/identifier/Select'
@@ -225,7 +229,18 @@ export default {
     },
     databaseExtraInfo () {
       return this.$config.databaseExtraInfo
+    },
+    databaseSize () {
+      if (!this.database) {
+        return null
+      }
+      let sum = 0
+      this.database.tables.forEach((t) => { sum += t.data_length })
+      return sizeToHumanLabel(sum)
     }
+  },
+  methods: {
+    sizeToHumanLabel
   }
 }
 </script>
diff --git a/dbrepo-ui/pages/database/_database_id/table/_table_id/info.vue b/dbrepo-ui/pages/database/_database_id/table/_table_id/info.vue
index d4b0620414afd29196250e01d1c8b150fa1b7b67..a074108ef3f11ee0a7ab85ae3462dd623dd08b47 100644
--- a/dbrepo-ui/pages/database/_database_id/table/_table_id/info.vue
+++ b/dbrepo-ui/pages/database/_database_id/table/_table_id/info.vue
@@ -17,9 +17,15 @@
               <v-list-item-title>
                 Table ID
               </v-list-item-title>
-              <v-list-item-content>
-                <span v-if="table && table.id">{{ table.id }}</span>
-              </v-list-item-content>
+              <v-list-item-content v-if="table && table.id" v-text="table.id" />
+              <v-list-item-title>
+                Table Size
+              </v-list-item-title>
+              <v-list-item-content v-if="table && table.data_length" v-text="sizeToHumanLabel(table.data_length)" />
+              <v-list-item-title>
+                Table Rows
+              </v-list-item-title>
+              <v-list-item-content v-if="table && table.num_rows" v-text="table.num_rows" />
               <v-list-item-title v-if="hasDescription" class="mt-2">
                 Table Description
               </v-list-item-title>
@@ -109,7 +115,7 @@
 import TableToolbar from '@/components/table/TableToolbar.vue'
 import Select from '@/components/identifier/Select'
 import Summary from '@/components/identifier/Summary'
-import { formatTimestampUTCLabel } from '@/utils'
+import { formatTimestampUTCLabel, sizeToHumanLabel } from '@/utils'
 import UserBadge from '@/components/UserBadge.vue'
 
 export default {
@@ -228,6 +234,7 @@ export default {
     }
   },
   methods: {
+    sizeToHumanLabel,
     amqpBadgeText (port) {
       if (port === 5672) {
         return 'insecure'
diff --git a/dbrepo-ui/utils/index.js b/dbrepo-ui/utils/index.js
index 3e08f463448d549aa1ab6d455fa3c3b8046557e8..c626b026d0d0469fd3bb79a670c9676a4e522ac3 100644
--- a/dbrepo-ui/utils/index.js
+++ b/dbrepo-ui/utils/index.js
@@ -1046,6 +1046,32 @@ function timestampsToHumanDifference (date1, date2) {
   return moment.duration(other.diff(date)).humanize(true)
 }
 
+function sizeToHumanLabel (num) {
+  let number = Number(num)
+  if (!number) {
+    return '0'
+  }
+  if (number < 1000) {
+    return `${Math.floor(number)} B`
+  }
+  number = number / 1000
+  if (number < 1000) {
+    return `${Math.floor(number)} kB`
+  }
+  number = number / 1000
+  if (number < 1000) {
+    return `${Math.floor(number)} MB`
+  }
+  number = number / 1000
+  if (number < 1000) {
+    return `${number} GB`
+  }
+  number = number / 1000
+  if (number < 1000) {
+    return `${number} TB`
+  }
+}
+
 module.exports = {
   notEmpty,
   formatTimestamp,
@@ -1061,5 +1087,6 @@ module.exports = {
   formatBinaryStream,
   languages,
   formatLanguage,
-  timestampsToHumanDifference
+  timestampsToHumanDifference,
+  sizeToHumanLabel
 }