diff --git a/dbrepo-discovery-service/rest-service/src/main/java/at/tuwien/config/GatewayConfig.java b/dbrepo-discovery-service/rest-service/src/main/java/at/tuwien/config/GatewayConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..cb0c9ffc9ee477fe22ec4a9ceb75d804285efe6f
--- /dev/null
+++ b/dbrepo-discovery-service/rest-service/src/main/java/at/tuwien/config/GatewayConfig.java
@@ -0,0 +1,32 @@
+package at.tuwien.config;
+
+import lombok.Getter;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.client.support.BasicAuthenticationInterceptor;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.DefaultUriBuilderFactory;
+
+@Getter
+@Configuration
+public class GatewayConfig {
+
+    @Value("${fda.gateway.endpoint}")
+    private String gatewayEndpoint;
+
+    @Value("${spring.rabbitmq.username}")
+    private String brokerUsername;
+
+    @Value("${spring.rabbitmq.password}")
+    private String brokerPassword;
+
+    @Bean("brokerRestTemplate")
+    public RestTemplate brokerRestTemplate() {
+        final RestTemplate restTemplate = new RestTemplate();
+        restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(gatewayEndpoint));
+        restTemplate.getInterceptors()
+                .add(new BasicAuthenticationInterceptor(brokerUsername, brokerPassword));
+        return restTemplate;
+    }
+}
diff --git a/dbrepo-discovery-service/rest-service/src/main/java/at/tuwien/service/JacksonConfig.java b/dbrepo-discovery-service/rest-service/src/main/java/at/tuwien/config/JacksonConfig.java
similarity index 97%
rename from dbrepo-discovery-service/rest-service/src/main/java/at/tuwien/service/JacksonConfig.java
rename to dbrepo-discovery-service/rest-service/src/main/java/at/tuwien/config/JacksonConfig.java
index 7720fff074b4c28c6ed4cf21f964df74afba29a3..fba7f99cf2bf1cbb12ac51cd6fd5b80751ff43c1 100644
--- a/dbrepo-discovery-service/rest-service/src/main/java/at/tuwien/service/JacksonConfig.java
+++ b/dbrepo-discovery-service/rest-service/src/main/java/at/tuwien/config/JacksonConfig.java
@@ -1,4 +1,4 @@
-package at.tuwien.service;
+package at.tuwien.config;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
diff --git a/dbrepo-discovery-service/rest-service/src/main/java/at/tuwien/service/ReadyConfig.java b/dbrepo-discovery-service/rest-service/src/main/java/at/tuwien/config/ReadyConfig.java
similarity index 95%
rename from dbrepo-discovery-service/rest-service/src/main/java/at/tuwien/service/ReadyConfig.java
rename to dbrepo-discovery-service/rest-service/src/main/java/at/tuwien/config/ReadyConfig.java
index ee5fb357f61b341618029f2676992addabac3e31..0bee3b961edd4ca456f0243c8eede630a4a54716 100644
--- a/dbrepo-discovery-service/rest-service/src/main/java/at/tuwien/service/ReadyConfig.java
+++ b/dbrepo-discovery-service/rest-service/src/main/java/at/tuwien/config/ReadyConfig.java
@@ -1,4 +1,4 @@
-package at.tuwien.service;
+package at.tuwien.config;
 
 import com.google.common.io.Files;
 import org.springframework.beans.factory.annotation.Value;
diff --git a/dbrepo-discovery-service/rest-service/src/main/resources/application-docker.yml b/dbrepo-discovery-service/rest-service/src/main/resources/application-docker.yml
deleted file mode 100644
index 967b742f9e3e7f4514211dd2971009dff253c04f..0000000000000000000000000000000000000000
--- a/dbrepo-discovery-service/rest-service/src/main/resources/application-docker.yml
+++ /dev/null
@@ -1,39 +0,0 @@
-app.version: '@project.version@'
-spring:
-  main.banner-mode: off
-  datasource:
-    url: jdbc:mariadb://metadata-db:3306/fda
-    driver-class-name: org.mariadb.jdbc.Driver
-    username: "${METADATA_USERNAME}"
-    password: "${METADATA_PASSWORD}"
-  jpa:
-    show-sql: false
-    database-platform: org.hibernate.dialect.MariaDBDialect
-    hibernate:
-      ddl-auto: validate
-      use-new-id-generator-mappings: false
-    open-in-view: false
-    properties:
-      hibernate:
-        default_schema: fda
-        jdbc:
-          time_zone: UTC
-  application:
-    name: discovery-service
-  cloud:
-    loadbalancer.ribbon.enabled: false
-management.endpoints.web.exposure.include: health,info,prometheus
-server.port: 9090
-logging:
-  pattern.console: "%d %highlight(%-5level) %msg%n"
-  level:
-    root: warn
-    at.tuwien.: "${LOG_LEVEL}"
-    org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug
-eureka:
-  eureka.client.register-with-eureka: false
-  eureka.client.fetch-registry: false
-  instance.hostname: discovery-service
-  client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/
-fda:
-  ready.path: /ready
\ No newline at end of file
diff --git a/dbrepo-discovery-service/rest-service/src/main/resources/application-local.yml b/dbrepo-discovery-service/rest-service/src/main/resources/application-local.yml
index 0d81e2101e6f9d729aefe3d2213d9ca1a3006590..1ab259ae3fe70e9b2b3e44c9f46c7dea341cc81a 100644
--- a/dbrepo-discovery-service/rest-service/src/main/resources/application-local.yml
+++ b/dbrepo-discovery-service/rest-service/src/main/resources/application-local.yml
@@ -20,6 +20,10 @@ spring:
           time_zone: UTC
   application:
     name: discovery-service
+  rabbitmq:
+    host: localhost
+    username: fda
+    password: fda
   cloud:
     loadbalancer.ribbon.enabled: false
     gateway:
@@ -46,4 +50,5 @@ eureka:
     secure-port-enabled: true
     secure-port: 9090
 fda:
-  ready.path: ./ready
\ No newline at end of file
+  ready.path: ./ready
+  gateway.endpoint: http://localhost:9095
\ No newline at end of file
diff --git a/dbrepo-discovery-service/rest-service/src/main/resources/application.yml b/dbrepo-discovery-service/rest-service/src/main/resources/application.yml
index 56b3f670d078e0998a668e5c401a8c2bc02c3a5a..3d691f1015f4b01cb4335c8835f0ae07dc112785 100644
--- a/dbrepo-discovery-service/rest-service/src/main/resources/application.yml
+++ b/dbrepo-discovery-service/rest-service/src/main/resources/application.yml
@@ -18,6 +18,10 @@ spring:
           time_zone: UTC
   application:
     name: discovery-service
+  rabbitmq:
+    host: broker-service
+    username: "${BROKER_USERNAME}"
+    password: "${BROKER_PASSWORD}"
   cloud:
     loadbalancer.ribbon.enabled: false
 management.endpoints.web.exposure.include: health,info,prometheus
@@ -40,4 +44,5 @@ eureka:
     secure-port-enabled: true
     secure-port: 9090
 fda:
-  ready.path: /ready
\ No newline at end of file
+  ready.path: /ready
+  gateway.endpoint: "${GATEWAY_ENDPOINT}"
\ No newline at end of file
diff --git a/dbrepo-discovery-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java b/dbrepo-discovery-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..c5adb93d3dddc50757d88380ed50857a1e034610
--- /dev/null
+++ b/dbrepo-discovery-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java
@@ -0,0 +1,9 @@
+package at.tuwien;
+
+import at.tuwien.test.BaseTest;
+import org.springframework.test.context.TestPropertySource;
+
+@TestPropertySource(locations = "classpath:application.properties")
+public abstract class BaseUnitTest extends BaseTest {
+
+}
\ No newline at end of file
diff --git a/dbrepo-discovery-service/rest-service/src/test/java/at/tuwien/MockServiceIntegrationTest.java b/dbrepo-discovery-service/rest-service/src/test/java/at/tuwien/MockServiceIntegrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..329ae7be2373a0eeb6eca51d5b16183d91ab3ed1
--- /dev/null
+++ b/dbrepo-discovery-service/rest-service/src/test/java/at/tuwien/MockServiceIntegrationTest.java
@@ -0,0 +1,37 @@
+package at.tuwien;
+
+import at.tuwien.config.H2Utils;
+import at.tuwien.service.MockService;
+import lombok.extern.log4j.Log4j2;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+
+@Log4j2
+@SpringBootTest
+public class MockServiceIntegrationTest extends BaseUnitTest {
+
+    @Autowired
+    private H2Utils h2Utils;
+
+    @Autowired
+    private MockService mockService;
+
+    @BeforeEach
+    public void beforeEach() {
+        h2Utils.runScript("schema.sql");
+    }
+
+    @Test
+    public void mock_succeeds() {
+
+        /* test */
+        final Boolean response = mockService.mock();
+        assertTrue(response);
+    }
+
+}
diff --git a/dbrepo-discovery-service/rest-service/src/test/resources/schema.sql b/dbrepo-discovery-service/rest-service/src/test/resources/schema.sql
new file mode 100644
index 0000000000000000000000000000000000000000..906d8df808fa8f79c1f7c1c26088c55da6c9ee9b
--- /dev/null
+++ b/dbrepo-discovery-service/rest-service/src/test/resources/schema.sql
@@ -0,0 +1,25 @@
+CREATE SCHEMA IF NOT EXISTS `fda`;
+SET SCHEMA `fda`;
+DROP TABLE IF EXISTS fda.mdb_concepts;
+CREATE TABLE IF NOT EXISTS fda.mdb_concepts
+(
+    uri        VARCHAR(500) not null,
+    name       VARCHAR(255),
+    created    timestamp    NOT NULL DEFAULT NOW(),
+    created_by bigint,
+    PRIMARY KEY (uri)
+);
+DROP TABLE IF EXISTS fda.mdb_units;
+CREATE TABLE IF NOT EXISTS fda.mdb_units
+(
+    uri        VARCHAR(500) not null,
+    name       VARCHAR(255),
+    created    timestamp    NOT NULL DEFAULT NOW(),
+    created_by bigint,
+    PRIMARY KEY (uri)
+);
+-- Modified for H2
+-- Assume id=1 is invalid
+-- Assume id=2 is still valid token
+-- CREATE VIEW IF NOT EXISTS fda.mdb_invalid_tokens AS
+-- (SELECT `id`, `token_hash`, `creator`, `created`, `expires`, `last_used` FROM fda.`mdb_tokens` WHERE `id` = 1);
\ No newline at end of file
diff --git a/dbrepo-metadata-service/pom.xml b/dbrepo-metadata-service/pom.xml
index ee05f0602cf9998b9ba21de61fc40d2485270b4c..7c352ef9663d56b514f6d596da0b8a8fad87b3e1 100644
--- a/dbrepo-metadata-service/pom.xml
+++ b/dbrepo-metadata-service/pom.xml
@@ -196,9 +196,10 @@
                         <exclude>at/tuwien/utils/**/*</exclude>
                         <exclude>at/tuwien/seeder/**/*</exclude>
                         <exclude>at/tuwien/mapper/**/*</exclude>
+                        <exclude>at/tuwien/handlers/**/*</exclude>
                         <exclude>at/tuwien/exception/**/*</exclude>
                         <exclude>at/tuwien/config/**/*</exclude>
-                        <exclude>**/DbrepoContainerManagingApplication.class</exclude>
+                        <exclude>**/DbrepoMetadataServiceApplication.class</exclude>
                     </excludes>
                 </configuration>
                 <executions>
diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MetadataEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MetadataEndpoint.java
index be5c02e7d1cb7a01290e2782e9e3e64fd491bd4c..728920ea268647995113ffcf7a2fd23b99616603 100644
--- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MetadataEndpoint.java
+++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MetadataEndpoint.java
@@ -47,7 +47,7 @@ public class MetadataEndpoint {
                     description = "List containers",
                     content = {@Content(mediaType = "text/xml")}),
     })
-    public ResponseEntity<?> identify() {
+    public ResponseEntity<String> identify() {
         log.debug("endpoint identify repository");
         return identifyAlt();
     }
@@ -60,7 +60,7 @@ public class MetadataEndpoint {
                     description = "List containers",
                     content = {@Content(mediaType = "text/xml")}),
     })
-    public ResponseEntity<?> identifyAlt() {
+    public ResponseEntity<String> identifyAlt() {
         log.debug("endpoint identify repository, verb=Identify");
         final String xml = metadataService.identify();
         log.trace("identify repository resulted in xml {}", xml);
@@ -70,7 +70,7 @@ public class MetadataEndpoint {
     @GetMapping(params = "verb=ListIdentifiers", produces = "text/xml;charset=UTF-8")
     @Timed(value = "identifiers.list", description = "Time needed to list the identifiers")
     @Operation(summary = "List the identifiers")
-    public ResponseEntity<?> listIdentifiers(OaiListIdentifiersParameters parameters) {
+    public ResponseEntity<String> listIdentifiers(OaiListIdentifiersParameters parameters) {
         log.debug("endpoint list identifiers, verb=ListIdentifiers, parameters={}", parameters);
         final String xml = metadataService.listIdentifiers(parameters);
         log.trace("list identifiers resulted in xml {}", xml);
@@ -80,9 +80,9 @@ public class MetadataEndpoint {
     @GetMapping(params = "verb=GetRecord", produces = "text/xml;charset=UTF-8")
     @Timed(value = "record.find", description = "Time needed to find a record")
     @Operation(summary = "Get the record")
-    public ResponseEntity<?> getRecord(OaiRecordParameters parameters) {
+    public ResponseEntity<String> getRecord(OaiRecordParameters parameters) {
         log.debug("endpoint get record, verb=GetRecord, parameters={}", parameters);
-        if (!parameters.getMetadataPrefix().equals("oai_dc")) {
+        if (parameters.getMetadataPrefix() != null && !parameters.getMetadataPrefix().equals("oai_dc")) {
             log.trace("metadataPrefix matches oai_dc, failed to serve this format");
             return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                     .body(metadataService.error(OaiErrorType.CANNOT_DISSEMINATE_FORMAT));
@@ -105,7 +105,7 @@ public class MetadataEndpoint {
     @GetMapping(params = "verb=ListMetadataFormats", produces = "text/xml;charset=UTF-8")
     @Timed(value = "formats.list", description = "Time needed to list the metadata formats")
     @Operation(summary = "List the metadata formats")
-    public ResponseEntity<?> listMetadataFormats() {
+    public ResponseEntity<String> listMetadataFormats() {
         log.debug("endpoint list metadata formats, verb=ListMetadataFormats");
         final String xml = metadataService.listMetadataFormats();
         log.trace("list metadata formats resulted in xml {}", xml);
diff --git a/dbrepo-metadata-service/rest-service/src/main/resources/templates/record.xml b/dbrepo-metadata-service/rest-service/src/main/resources/templates/record.xml
index dd5c7df1a0a25d67555acd63e588621d6013fffe..1574f72adc68c04446d33179431590561545ffaf 100644
--- a/dbrepo-metadata-service/rest-service/src/main/resources/templates/record.xml
+++ b/dbrepo-metadata-service/rest-service/src/main/resources/templates/record.xml
@@ -10,7 +10,7 @@
                 <dc:title>[[${title}]]</dc:title>
                 <dc:publisher>[[${publisher}]]</dc:publisher>
                 <dc:description>[[${description}]]</dc:description>
-                <dc:creator th:each="creator: ${identifier.getCreators()}">[(${creator.getLastname()})], [(${creator.getFirstname()})]</dc:creator>
+                <dc:creator th:each="creator: ${creators}">[(${creator.getLastname()})], [(${creator.getFirstname()})]</dc:creator>
             </oai_dc:dc>
         </metadata>
     </record>
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/MetadataEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/MetadataEndpointUnitTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..d06533308a7bf6477ab0141bb285bb1a77219d64
--- /dev/null
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/MetadataEndpointUnitTest.java
@@ -0,0 +1,171 @@
+package at.tuwien.endpoints;
+
+import at.tuwien.BaseUnitTest;
+import at.tuwien.OaiListIdentifiersParameters;
+import at.tuwien.OaiRecordParameters;
+import at.tuwien.config.H2Utils;
+import at.tuwien.entities.identifier.Identifier;
+import at.tuwien.exception.IdentifierNotFoundException;
+import at.tuwien.repository.jpa.*;
+import at.tuwien.service.IdentifierService;
+import lombok.extern.log4j.Log4j2;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import java.util.List;
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.when;
+
+@Log4j2
+@SpringBootTest
+@ExtendWith(SpringExtension.class)
+public class MetadataEndpointUnitTest extends BaseUnitTest {
+
+    @MockBean
+    private IdentifierRepository identifierRepository;
+
+    @Autowired
+    private MetadataEndpoint metadataEndpoint;
+
+    @Autowired
+    private H2Utils h2Utils;
+
+    @BeforeEach
+    public void beforeEach() {
+        /* schema */
+        h2Utils.runScript("schema.sql");
+    }
+
+    @Test
+    public void identify_succeeds() {
+
+        /* test */
+        final ResponseEntity<String> response = metadataEndpoint.identify();
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+        final String body = response.getBody();
+        assertNotNull(body);
+    }
+
+    @Test
+    public void identifyAlt_succeeds() {
+
+        /* test */
+        final ResponseEntity<String> response = metadataEndpoint.identifyAlt();
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+        final String body = response.getBody();
+        assertNotNull(body);
+    }
+
+    @Test
+    public void listIdentifiers_succeeds() {
+        final OaiListIdentifiersParameters parameters = new OaiListIdentifiersParameters();
+
+        /* mock */
+        when(identifierRepository.findAll())
+                .thenReturn(List.of(IDENTIFIER_1));
+
+        /* test */
+        final ResponseEntity<String> response = metadataEndpoint.listIdentifiers(parameters);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+        final String body = response.getBody();
+        assertNotNull(body);
+    }
+
+    @Test
+    public void getRecord_formatMissing_fails() {
+        final OaiRecordParameters parameters = new OaiRecordParameters();
+
+        /* mock */
+        when(identifierRepository.findById(IDENTIFIER_1_ID))
+                .thenReturn(Optional.of(IDENTIFIER_1));
+
+        /* test */
+        final ResponseEntity<?> response = metadataEndpoint.getRecord(parameters);
+        assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
+    }
+
+    @Test
+    public void getRecord_unsupportedFormat_fails() {
+        final OaiRecordParameters parameters = new OaiRecordParameters();
+        parameters.setMetadataPrefix("oai_marc");
+
+        /* mock */
+        when(identifierRepository.findById(IDENTIFIER_1_ID))
+                .thenReturn(Optional.of(IDENTIFIER_1));
+
+        /* test */
+        final ResponseEntity<?> response = metadataEndpoint.getRecord(parameters);
+        assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
+    }
+
+    @Test
+    public void getRecord_noIdentifier_fails() {
+        final OaiRecordParameters parameters = new OaiRecordParameters();
+        parameters.setMetadataPrefix("oai_dc");
+
+        /* mock */
+        when(identifierRepository.findById(IDENTIFIER_1_ID))
+                .thenReturn(Optional.of(IDENTIFIER_1));
+
+        /* test */
+        final ResponseEntity<?> response = metadataEndpoint.getRecord(parameters);
+        assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
+    }
+
+    @Test
+    public void getRecord_succeeds() {
+        final OaiRecordParameters parameters = new OaiRecordParameters();
+        parameters.setMetadataPrefix("oai_dc");
+        parameters.setIdentifier(Long.toString(1L));
+
+        /* mock */
+        when(identifierRepository.findById(IDENTIFIER_1_ID))
+                .thenReturn(Optional.of(IDENTIFIER_1));
+
+        /* test */
+        final ResponseEntity<String> response = metadataEndpoint.getRecord(parameters);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+        final String body = response.getBody();
+        assertNotNull(body);
+    }
+
+    @Test
+    public void getRecord_notFound_fails() {
+        final OaiRecordParameters parameters = new OaiRecordParameters();
+        parameters.setMetadataPrefix("oai_dc");
+        parameters.setIdentifier(Long.toString(9999L));
+
+        /* mock */
+        when(identifierRepository.findById(IDENTIFIER_1_ID))
+                .thenReturn(Optional.of(IDENTIFIER_1));
+
+        /* test */
+        final ResponseEntity<?> response = metadataEndpoint.getRecord(parameters);
+        assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode());
+    }
+
+    @Test
+    public void listMetadataFormats_succeeds() {
+
+        /* mock */
+        when(identifierRepository.findById(IDENTIFIER_1_ID))
+                .thenReturn(Optional.of(IDENTIFIER_1));
+
+        /* test */
+        final ResponseEntity<String> response = metadataEndpoint.listMetadataFormats();
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+        final String body = response.getBody();
+        assertNotNull(body);
+    }
+
+}
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceIntegrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..54f9367e07cd0dd7040ea75a201e7d36fcc0c4ba
--- /dev/null
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceIntegrationTest.java
@@ -0,0 +1,91 @@
+package at.tuwien.service;
+
+import at.tuwien.BaseUnitTest;
+import at.tuwien.config.H2Utils;
+import at.tuwien.entities.identifier.Identifier;
+import at.tuwien.exception.IdentifierNotFoundException;
+import at.tuwien.repository.jpa.*;
+import lombok.extern.log4j.Log4j2;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+@Log4j2
+@SpringBootTest
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
+@ExtendWith(SpringExtension.class)
+public class IdentifierServiceIntegrationTest extends BaseUnitTest {
+
+    @Autowired
+    private ImageRepository imageRepository;
+
+    @Autowired
+    private ContainerRepository containerRepository;
+
+    @Autowired
+    private DatabaseRepository databaseRepository;
+
+    @Autowired
+    private UserRepository userRepository;
+
+    @Autowired
+    private RealmRepository realmRepository;
+
+    @Autowired
+    private IdentifierRepository identifierRepository;
+
+    @Autowired
+    private IdentifierService identifierService;
+
+    @Autowired
+    private H2Utils h2Utils;
+
+    @BeforeEach
+    public void beforeEach() {
+        /* schema */
+        h2Utils.runScript("schema.sql");
+        /* metadata database */
+        imageRepository.save(IMAGE_1_SIMPLE);
+        realmRepository.save(REALM_DBREPO);
+        userRepository.save(USER_1_SIMPLE);
+        containerRepository.save(CONTAINER_1_SIMPLE);
+        databaseRepository.save(DATABASE_1_SIMPLE);
+        identifierRepository.save(IDENTIFIER_1_SIMPLE);
+    }
+
+    @Test
+    public void findAll_succeeds() {
+
+        /* test */
+        final List<Identifier> response = identifierService.findAll();
+        assertEquals(1, response.size());
+    }
+
+    @Test
+    public void find_succeeds() throws IdentifierNotFoundException {
+
+        /* test */
+        final Identifier response = identifierService.find(IDENTIFIER_1_ID);
+        assertEquals(IDENTIFIER_1_ID, response.getId());
+        assertEquals(IDENTIFIER_1_TITLE, response.getTitle());
+    }
+
+    @Test
+    public void find_fails() {
+
+        /* test */
+        assertThrows(IdentifierNotFoundException.class, () -> {
+            identifierService.find(IDENTIFIER_2_ID);
+        });
+    }
+
+}
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/MetadataServiceIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/MetadataServiceIntegrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..3fcaa1a83813f1ee73414a4089197c7dc598fb98
--- /dev/null
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/MetadataServiceIntegrationTest.java
@@ -0,0 +1,135 @@
+package at.tuwien.service;
+
+import at.tuwien.BaseUnitTest;
+import at.tuwien.OaiErrorType;
+import at.tuwien.OaiListIdentifiersParameters;
+import at.tuwien.OaiRecordParameters;
+import at.tuwien.config.H2Utils;
+import at.tuwien.exception.IdentifierNotFoundException;
+import at.tuwien.repository.jpa.*;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@Log4j2
+@SpringBootTest
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
+@ExtendWith(SpringExtension.class)
+public class MetadataServiceIntegrationTest extends BaseUnitTest {
+
+    @Autowired
+    private ImageRepository imageRepository;
+
+    @Autowired
+    private ContainerRepository containerRepository;
+
+    @Autowired
+    private DatabaseRepository databaseRepository;
+
+    @Autowired
+    private UserRepository userRepository;
+
+    @Autowired
+    private RealmRepository realmRepository;
+
+    @Autowired
+    private IdentifierRepository identifierRepository;
+
+    @Autowired
+    private MetadataService metadataService;
+
+    @Autowired
+    private H2Utils h2Utils;
+
+    @BeforeEach
+    public void beforeEach() {
+        /* schema */
+        h2Utils.runScript("schema.sql");
+        /* metadata database */
+        imageRepository.save(IMAGE_1_SIMPLE);
+        realmRepository.save(REALM_DBREPO);
+        userRepository.save(USER_1_SIMPLE);
+        containerRepository.save(CONTAINER_1_SIMPLE);
+        databaseRepository.save(DATABASE_1_SIMPLE);
+        identifierRepository.save(IDENTIFIER_1_SIMPLE);
+    }
+
+    @Test
+    public void identify_succeeds() {
+
+        /* test */
+        final String response = metadataService.identify();
+        assertTrue(response.contains("repositoryName"));
+        assertTrue(response.contains("baseURL"));
+        assertTrue(response.contains("adminEmail"));
+        assertTrue(response.contains("earliestDatestamp"));
+        assertTrue(response.contains("deletedRecord"));
+        assertTrue(response.contains("granularity"));
+    }
+
+    @Test
+    public void listIdentifiers_succeeds() {
+        final OaiListIdentifiersParameters parameters = new OaiListIdentifiersParameters();
+
+        /* test */
+        final String response = metadataService.listIdentifiers(parameters);
+        assertTrue(response.contains("identifier"));
+        assertTrue(response.contains("datestamp"));
+    }
+
+    @Test
+    public void listMetadataFormats_succeeds() {
+
+        /* test */
+        final String response = metadataService.listMetadataFormats();
+        assertTrue(response.contains("metadataPrefix"));
+        assertTrue(response.contains("schema"));
+        assertTrue(response.contains("metadataNamespace"));
+    }
+
+    @Test
+    public void error_succeeds() {
+
+        /* test */
+        final String response = metadataService.error(OaiErrorType.CANNOT_DISSEMINATE_FORMAT);
+        assertTrue(response.contains("error"));
+    }
+
+    @Test
+    public void getRecord_succeeds() throws IdentifierNotFoundException {
+        final OaiRecordParameters parameters = new OaiRecordParameters();
+        parameters.setIdentifier(Long.toString(1L));
+
+        /* test */
+        final String response = metadataService.getRecord(parameters);
+        assertTrue(response.contains("identifier"));
+        assertTrue(response.contains("datestamp"));
+        assertTrue(response.contains("title"));
+        assertTrue(response.contains("description"));
+        assertTrue(response.contains("publisher"));
+    }
+
+    @Test
+    public void getRecord_fails() {
+        final OaiRecordParameters parameters = new OaiRecordParameters();
+        parameters.setIdentifier(Long.toString(9999L));
+
+        /* test */
+        assertThrows(IdentifierNotFoundException.class, () -> {
+            metadataService.getRecord(parameters);
+        });
+    }
+
+}
diff --git a/dbrepo-metadata-service/rest-service/src/test/resources/schema.sql b/dbrepo-metadata-service/rest-service/src/test/resources/schema.sql
new file mode 100644
index 0000000000000000000000000000000000000000..906d8df808fa8f79c1f7c1c26088c55da6c9ee9b
--- /dev/null
+++ b/dbrepo-metadata-service/rest-service/src/test/resources/schema.sql
@@ -0,0 +1,25 @@
+CREATE SCHEMA IF NOT EXISTS `fda`;
+SET SCHEMA `fda`;
+DROP TABLE IF EXISTS fda.mdb_concepts;
+CREATE TABLE IF NOT EXISTS fda.mdb_concepts
+(
+    uri        VARCHAR(500) not null,
+    name       VARCHAR(255),
+    created    timestamp    NOT NULL DEFAULT NOW(),
+    created_by bigint,
+    PRIMARY KEY (uri)
+);
+DROP TABLE IF EXISTS fda.mdb_units;
+CREATE TABLE IF NOT EXISTS fda.mdb_units
+(
+    uri        VARCHAR(500) not null,
+    name       VARCHAR(255),
+    created    timestamp    NOT NULL DEFAULT NOW(),
+    created_by bigint,
+    PRIMARY KEY (uri)
+);
+-- Modified for H2
+-- Assume id=1 is invalid
+-- Assume id=2 is still valid token
+-- CREATE VIEW IF NOT EXISTS fda.mdb_invalid_tokens AS
+-- (SELECT `id`, `token_hash`, `creator`, `created`, `expires`, `last_used` FROM fda.`mdb_tokens` WHERE `id` = 1);
\ No newline at end of file
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/repository/jpa/ContainerRepository.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/repository/jpa/ContainerRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..d692b00041998c9ac88e35465508fab23be7d674
--- /dev/null
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/repository/jpa/ContainerRepository.java
@@ -0,0 +1,9 @@
+package at.tuwien.repository.jpa;
+
+import at.tuwien.entities.container.Container;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ContainerRepository extends JpaRepository<Container, Long> {
+}
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/repository/jpa/DatabaseRepository.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/repository/jpa/DatabaseRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..ae76b3951eb6f139358713c33cb2a4b3acad8ec7
--- /dev/null
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/repository/jpa/DatabaseRepository.java
@@ -0,0 +1,9 @@
+package at.tuwien.repository.jpa;
+
+import at.tuwien.entities.database.Database;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface DatabaseRepository extends JpaRepository<Database, Long> {
+}
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/repository/jpa/ImageRepository.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/repository/jpa/ImageRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..c033bd17dc63c7c0f8cb8b2354c689578d3eccf7
--- /dev/null
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/repository/jpa/ImageRepository.java
@@ -0,0 +1,9 @@
+package at.tuwien.repository.jpa;
+
+import at.tuwien.entities.container.image.ContainerImage;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ImageRepository extends JpaRepository<ContainerImage, Long> {
+}
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/repository/jpa/RealmRepository.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/repository/jpa/RealmRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..6a2a5443d938b9cad6e10d40114ef4d0f5f950db
--- /dev/null
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/repository/jpa/RealmRepository.java
@@ -0,0 +1,11 @@
+package at.tuwien.repository.jpa;
+
+import at.tuwien.entities.user.Realm;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.UUID;
+
+@Repository
+public interface RealmRepository extends JpaRepository<Realm, UUID> {
+}
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/repository/jpa/UserRepository.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/repository/jpa/UserRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..3dbd267234e83405566ae6c9f5efe3260d38b875
--- /dev/null
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/repository/jpa/UserRepository.java
@@ -0,0 +1,11 @@
+package at.tuwien.repository.jpa;
+
+import at.tuwien.entities.user.User;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.UUID;
+
+@Repository
+public interface UserRepository extends JpaRepository<User, UUID> {
+}
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 5b87576ad931e97454d02827d94d9b4b4f470856..09cf17d37b81728bda86ee3aefb6b7397d6d7fed 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
@@ -2,7 +2,7 @@ package at.tuwien.service.impl;
 
 import at.tuwien.entities.identifier.Identifier;
 import at.tuwien.exception.IdentifierNotFoundException;
-import at.tuwien.repository.jpa.IdentifierRepository;
+import at.tuwien.repository.jpa.*;
 import at.tuwien.service.IdentifierService;
 import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/MetadataServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/MetadataServiceImpl.java
index d197913a03d03f625d46644a5351a973675bf0e2..78a089213ae37eb4292c56da3db5cc6148489cc5 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/MetadataServiceImpl.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/MetadataServiceImpl.java
@@ -74,6 +74,7 @@ public class MetadataServiceImpl implements MetadataService {
         final Identifier identifier = identifierService.find(id);
         final Context context = new Context();
         context.setVariable("identifier", identifier.getId());
+        context.setVariable("creators", identifier.getCreators());
         context.setVariable("datestamp", metadataMapper.instantToDatestamp(identifier.getCreated()));
         context.setVariable("title", identifier.getTitle());
         context.setVariable("description", identifier.getDescription());