diff --git a/pom.xml b/pom.xml
index 7a61d87a30caa3a6f43b1af5fe2500c35158ec36..32753189cd392b7c39833a0dd71a4875b94af617 100644
--- a/pom.xml
+++ b/pom.xml
@@ -578,51 +578,11 @@
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-surefire-plugin</artifactId>
 				<configuration>
-					<excludes>
-						<exclude>*IT.java</exclude>
-						<exclude>*ITest.java</exclude>
-					</excludes>
-					<environmentVariables>
-						<SPRING_PROFILES_ACTIVE>${spring.testprofile}</SPRING_PROFILES_ACTIVE>
-					</environmentVariables>
-					<!--argLine>
-						${surefire.jacoco.args}
-					</argLine-->
-
-					<!--properties>
-						<configurationParameters>
-							junit.jupiter.extensions.autodetection.enabled = true
-							junit.jupiter.execution.parallel.enabled = true
-						</configurationParameters>
-					</properties-->
-				</configuration>
-			</plugin>
-			<!-- Integrationstests -->
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-failsafe-plugin</artifactId>
-				<configuration>
-					<additionalClasspathElements>
-						<additionalClasspathElement>
-							${project.build.directory}/classes
-						</additionalClasspathElement>
-					</additionalClasspathElements>
 					<includes>
-						<include>*ITest.java</include>
-						<include>*IT.java</include>
+						<include>**/*Test.java</include>
+						<include>**/*ITCase.java</include>
 					</includes>
-					<reportsDirectory>
-						${project.build.directory}/surefire-reports
-					</reportsDirectory>
 				</configuration>
-				<executions>
-					<execution>
-						<goals>
-							<goal>integration-test</goal>
-							<goal>verify</goal>
-						</goals>
-					</execution>
-				</executions>
 			</plugin>
 			<plugin>
 				<groupId>org.jacoco</groupId>
diff --git a/src/main/java/de/ozgcloud/xta/test/app/config/ClientConnectionProperties.java b/src/main/java/de/ozgcloud/xta/test/app/config/ClientConnectionProperties.java
deleted file mode 100644
index e7a1c8fccc24fb674313afe264d1662f90ea727f..0000000000000000000000000000000000000000
--- a/src/main/java/de/ozgcloud/xta/test/app/config/ClientConnectionProperties.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * @formatter:off
- *
- * Copyright 2021-2022  Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the European Public License, Version 1.2 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     https://opensource.org/licenses/EUPL-1.2
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * @formatter:on
- */
-package de.ozgcloud.xta.test.app.config;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class ClientConnectionProperties {
-
-	private String managementPort;
-	private String sendPort;
-	private String msgBoxPort;
-
-	public ClientConnectionProperties(final ClientConnectionProperties ccp) {
-		managementPort = ccp.getManagementPort();
-		sendPort = ccp.getSendPort();
-		msgBoxPort = ccp.getMsgBoxPort();
-	}
-}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/config/ClientProperties.java b/src/main/java/de/ozgcloud/xta/test/app/config/ClientProperties.java
deleted file mode 100644
index 141d66501a7aad1c911ab28c89dcc930caddc4f7..0000000000000000000000000000000000000000
--- a/src/main/java/de/ozgcloud/xta/test/app/config/ClientProperties.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * @formatter:off
- *
- * Copyright 2021-2022  Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the European Public License, Version 1.2 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     https://opensource.org/licenses/EUPL-1.2
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * @formatter:on
- */
-package de.ozgcloud.xta.test.app.config;
-
-import jakarta.validation.constraints.NotNull;
-
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.FileSystemResource;
-import org.springframework.core.io.Resource;
-import org.springframework.validation.annotation.Validated;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-
-import lombok.Data;
-
-@Data
-@Validated
-public class ClientProperties {
-
-	private ClientConnectionProperties serverUrl;
-
-	private boolean checkHostnameInCertificate = true;
-
-	@NotNull
-	private String keyStore;
-
-	@NotNull
-	private String keyStorePassword;
-
-	@NotNull
-	private String keyPassword;
-
-	private String keyAlias;
-
-	@NotNull
-	private String trustStore;
-
-	@NotNull
-	private String trustStorePassword;
-
-	public ClientProperties() {
-	}
-
-	public ClientProperties(final ClientProperties cp) {
-		serverUrl = new ClientConnectionProperties(cp.getServerUrl());
-		checkHostnameInCertificate = cp.isCheckHostnameInCertificate();
-		keyStore = cp.getKeyStore();
-		keyStorePassword = cp.getKeyStorePassword();
-		keyPassword = cp.getKeyPassword();
-		keyAlias = cp.getKeyAlias();
-		trustStore = cp.getTrustStore();
-		trustStorePassword = cp.getTrustStorePassword();
-	}
-
-	@JsonIgnore
-	public Resource getKeyStoreAsResource() {
-		return getResource(keyStore);
-	}
-
-	@JsonIgnore
-	public Resource getTrustStoreAsResource() {
-		return getResource(trustStore);
-	}
-
-	private Resource getResource(final String resourceLocation) {
-		if (resourceLocation.startsWith("classpath:")) {
-			return new ClassPathResource(resourceLocation.substring("classpath:".length()));
-		}
-		if (resourceLocation.startsWith("file:")) {
-			return new FileSystemResource(resourceLocation.substring("file:".length()));
-		}
-		return new FileSystemResource(resourceLocation);
-	}
-}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/config/MapStructConfiguration.java b/src/main/java/de/ozgcloud/xta/test/app/config/MapStructConfiguration.java
deleted file mode 100644
index 4b1f76bef66ef1b7688bca081e8d5a81c8577b8a..0000000000000000000000000000000000000000
--- a/src/main/java/de/ozgcloud/xta/test/app/config/MapStructConfiguration.java
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Created 2023-03-24
- */
-package de.ozgcloud.xta.test.app.config;
-
-import org.mapstruct.MapperConfig;
-import org.mapstruct.ReportingPolicy;
-
-@MapperConfig(componentModel = "spring", unmappedSourcePolicy = ReportingPolicy.WARN, unmappedTargetPolicy = ReportingPolicy.ERROR)
-public class MapStructConfiguration {
-}
\ No newline at end of file
diff --git a/src/main/java/de/ozgcloud/xta/test/app/config/XTAServer.java b/src/main/java/de/ozgcloud/xta/test/app/config/XTAServer.java
index be7b9731318139ff1f98f4bb007b0bcb201d3c0c..f5fd91b9978836dc5d771de05e2941b235a17cba 100644
--- a/src/main/java/de/ozgcloud/xta/test/app/config/XTAServer.java
+++ b/src/main/java/de/ozgcloud/xta/test/app/config/XTAServer.java
@@ -5,21 +5,21 @@ import jakarta.xml.ws.soap.SOAPBinding;
 
 import org.apache.cxf.bus.spring.SpringBus;
 import org.apache.cxf.jaxws.EndpointImpl;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
 import genv3.de.xoev.transport.xta.x211.ManagementPortType;
 import genv3.de.xoev.transport.xta.x211.MsgBoxPortType;
 import genv3.de.xoev.transport.xta.x211.SendPortType;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
 
 @Configuration
 @Log4j2
+@RequiredArgsConstructor
 public class XTAServer {
 
-	@Autowired
-	private SpringBus bus;
+	private final SpringBus bus;
 
 	@Bean
 	Endpoint managementEndpoint(final ManagementPortType managementPortType) {
diff --git a/src/main/java/de/ozgcloud/xta/test/app/config/XtaConfigQualifierType.java b/src/main/java/de/ozgcloud/xta/test/app/config/XtaConfigQualifierType.java
deleted file mode 100644
index 1e8f97f99a0c5bfce4dbf57a5eb62519701cbd2a..0000000000000000000000000000000000000000
--- a/src/main/java/de/ozgcloud/xta/test/app/config/XtaConfigQualifierType.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package de.ozgcloud.xta.test.app.config;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-
-import lombok.Data;
-
-@Data
-public class XtaConfigQualifierType {
-
-	private String qualifierSubject;
-
-	private String qualifierService;
-
-	@JsonIgnore
-	private final String messageTypeName = null; // was removed from UI and should generally be null
-
-	private String messageTypeCode;
-
-	@JsonIgnore
-	private final String messageTypeListUri = "urn:de:payloadSchema:elementName";
-
-	@JsonIgnore
-	private final String messageTypeListVersionId = "1.0";
-
-	private String messageTypePayloadSchema;
-
-	@JsonIgnore
-	private final String businessScenarioName = null; // was removed from UI and should generally be null
-
-	private String businessScenarioCode;
-
-	private String businessScenarioListUri;
-
-	private String businessScenarioListVersionId;
-
-	private boolean businessScenarioUseUndefined;
-
-	private String businessScenarioUndefined;
-}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/config/XtaTesterConfiguration.java b/src/main/java/de/ozgcloud/xta/test/app/config/XtaTesterConfiguration.java
deleted file mode 100644
index 1af769354d82891c84c03e76e08a6d440ab4645c..0000000000000000000000000000000000000000
--- a/src/main/java/de/ozgcloud/xta/test/app/config/XtaTesterConfiguration.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * @formatter:off
- *
- * Copyright 2021-2022  Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the European Public License, Version 1.2 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     https://opensource.org/licenses/EUPL-1.2
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * @formatter:on
- */
-package de.ozgcloud.xta.test.app.config;
-
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-@Configuration
-public class XtaTesterConfiguration implements WebMvcConfigurer {
-
-	@Override
-	public void addResourceHandlers(final ResourceHandlerRegistry registry) {
-		registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
-	}
-}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/data/XtaMessageRepository.java b/src/main/java/de/ozgcloud/xta/test/app/data/XtaMessageRepository.java
index d24dca076ae0ee47114f01518482e5f261d3f82d..b84e9826039df4c04a2f07f66ed42e992f74c1e3 100644
--- a/src/main/java/de/ozgcloud/xta/test/app/data/XtaMessageRepository.java
+++ b/src/main/java/de/ozgcloud/xta/test/app/data/XtaMessageRepository.java
@@ -31,13 +31,15 @@ public class XtaMessageRepository {
 		return Optional.ofNullable(messages.get(messageId));
 	}
 
-	public void delete(String messageId) {
+	public boolean delete(String messageId) {
 		if (messages.containsKey(messageId)) {
 			var message = messages.get(messageId);
 			message.attachmentFiles().forEach(this::silentDeleteFile);
 			silentDeleteFile(message.messageFile());
+			messages.remove(messageId);
+			return true;
 		}
-		messages.remove(messageId);
+		return false;
 	}
 
 	private void silentDeleteFile(XtaFile xtaFile) {
@@ -62,4 +64,11 @@ public class XtaMessageRepository {
 		return messages.values().stream()
 				.filter(m -> m.metaData().readerIdentifier().value().equals(readerIdentifierValue));
 	}
+
+	public boolean deleteByMessageIdAndReaderIdentifierValue(String messageId, String readerIdentifierValue) {
+		return get(messageId)
+				.filter(m -> m.metaData().readerIdentifier().value().equals(readerIdentifierValue))
+				.map(m -> delete(messageId))
+				.orElse(false);
+	}
 }
diff --git a/src/main/java/de/ozgcloud/xta/test/app/exception/CancelScenarioExecution.java b/src/main/java/de/ozgcloud/xta/test/app/exception/CancelScenarioExecution.java
deleted file mode 100644
index b5e177e10d839a7a8c2509046f9b08c841fc50ba..0000000000000000000000000000000000000000
--- a/src/main/java/de/ozgcloud/xta/test/app/exception/CancelScenarioExecution.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * @formatter:off
- *
- * Copyright 2021-2022  Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the European Public License, Version 1.2 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     https://opensource.org/licenses/EUPL-1.2
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * @formatter:on
- */
-package de.ozgcloud.xta.test.app.exception;
-
-public class CancelScenarioExecution extends RuntimeException {
-
-	private static final long serialVersionUID = 3131526610326559836L;
-
-	public CancelScenarioExecution(final String message, final Throwable cause) {
-		super(message, cause);
-	}
-
-	public CancelScenarioExecution(final String message) {
-		super(message);
-	}
-
-	public CancelScenarioExecution(final Throwable cause) {
-		super(cause);
-	}
-}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/exception/ConfigurationException.java b/src/main/java/de/ozgcloud/xta/test/app/exception/ConfigurationException.java
deleted file mode 100644
index 7ffc17148f661599c1903106a98784c19fd7437e..0000000000000000000000000000000000000000
--- a/src/main/java/de/ozgcloud/xta/test/app/exception/ConfigurationException.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * @formatter:off
- *
- * Copyright 2021-2022  Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the European Public License, Version 1.2 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     https://opensource.org/licenses/EUPL-1.2
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * @formatter:on
- */
-package de.ozgcloud.xta.test.app.exception;
-
-public class ConfigurationException extends RuntimeException {
-
-	private static final long serialVersionUID = 7289416637437590349L;
-
-	public ConfigurationException(final String message, final Throwable cause) {
-		super(message, cause);
-	}
-
-	public ConfigurationException(final String message) {
-		super(message);
-	}
-
-	public ConfigurationException(final Throwable cause) {
-		super(cause);
-	}
-}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/exception/XtaTesterException.java b/src/main/java/de/ozgcloud/xta/test/app/exception/XtaTesterException.java
deleted file mode 100644
index 9c1dd1565af0355d7baff3813572b15ed2023b8b..0000000000000000000000000000000000000000
--- a/src/main/java/de/ozgcloud/xta/test/app/exception/XtaTesterException.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * @formatter:off
- *
- * Copyright 2021-2022  Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the European Public License, Version 1.2 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     https://opensource.org/licenses/EUPL-1.2
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * @formatter:on
- */
-package de.ozgcloud.xta.test.app.exception;
-
-public class XtaTesterException extends Exception {
-
-	private static final long serialVersionUID = -4170994559864389457L;
-
-	public XtaTesterException(final String message, final Throwable cause) {
-		super(message, cause);
-	}
-
-	public XtaTesterException(final String message) {
-		super(message);
-	}
-
-	public XtaTesterException(final Throwable cause) {
-		super(cause);
-	}
-}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/mapper/ExceptionMapper.java b/src/main/java/de/ozgcloud/xta/test/app/mapper/ExceptionMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..e9aa8168c7ea74260b386fec92bb0c45fcde91c8
--- /dev/null
+++ b/src/main/java/de/ozgcloud/xta/test/app/mapper/ExceptionMapper.java
@@ -0,0 +1,62 @@
+package de.ozgcloud.xta.test.app.mapper;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.ReportingPolicy;
+
+import genv3.de.xoev.transport.xta.x211.CodeFehlernummer;
+import genv3.de.xoev.transport.xta.x211.InvalidMessageIDException;
+import genv3.de.xoev.transport.xta.x211.InvalidMessageIDExceptionType;
+import genv3.de.xoev.transport.xta.x211.ParameterIsNotValidException;
+import genv3.de.xoev.transport.xta.x211.ParameterIsNotValidExceptionType;
+import genv3.de.xoev.transport.xta.x211.XTAWSTechnicalProblemException;
+import genv3.de.xoev.transport.xta.x211.XTAWSTechnicalProblemExceptionType;
+
+@Mapper(
+		unmappedTargetPolicy = ReportingPolicy.ERROR
+)
+public interface ExceptionMapper {
+
+	String ERROR_CODE_LIST_URN = "urn:de:xta:webservice:codeliste:fehlernummer";
+	String ERROR_CODE_LIST_VERSION = "1.0";
+	String ERROR_CODE_PARAMETER_MISSING = "9020";
+	String ERROR_CODE_PARAMETER_MISSING_DESCRIPTION = "Notwendige Parameter nicht vorhanden";
+	String ERROR_CODE_INTERNAL_TECHNICAL_PROBLEM = "9030";
+	String ERROR_CODE_INTERNAL_TECHNICAL_PROBLEM_DESCRIPTION = "Interner Fehler beim XTA-Server bzw. XTA-Dienstleister";
+	String ERROR_CODE_MESSAGE_ID_UNKNOWN = "9070";
+	String ERROR_CODE_MESSAGE_ID_UNKNOWN_DESCRIPTION = "MessageID für den Account nicht bekannt";
+
+	default InvalidMessageIDException createInvalidMessageIDException(String message) {
+		return new InvalidMessageIDException(
+				message,
+				mapInvalidMessageIDExceptionType(ERROR_CODE_MESSAGE_ID_UNKNOWN, ERROR_CODE_MESSAGE_ID_UNKNOWN_DESCRIPTION)
+		);
+	}
+
+	@Mapping(target = "errorCode", expression = "java( mapCodeFehlernummer(code, name) )")
+	InvalidMessageIDExceptionType mapInvalidMessageIDExceptionType(String code, String name);
+
+	default XTAWSTechnicalProblemException createTechnicalProblemException(String message) {
+		return new XTAWSTechnicalProblemException(
+				message,
+				mapXTAWSTechnicalProblemExceptionType(ERROR_CODE_INTERNAL_TECHNICAL_PROBLEM, ERROR_CODE_INTERNAL_TECHNICAL_PROBLEM_DESCRIPTION)
+		);
+	}
+
+	@Mapping(target = "errorCode", expression = "java( mapCodeFehlernummer(code, name) )")
+	XTAWSTechnicalProblemExceptionType mapXTAWSTechnicalProblemExceptionType(String code, String name);
+
+	default ParameterIsNotValidException createParameterIsNotValidException(String message) {
+		return new ParameterIsNotValidException(
+				message,
+				mapParameterIsNotValidExceptionType(ERROR_CODE_PARAMETER_MISSING, ERROR_CODE_PARAMETER_MISSING_DESCRIPTION)
+		);
+	}
+
+	@Mapping(target = "errorCode", expression = "java( mapCodeFehlernummer(code, name) )")
+	ParameterIsNotValidExceptionType mapParameterIsNotValidExceptionType(String code, String name);
+
+	@Mapping(target = "listURI", constant = ERROR_CODE_LIST_URN)
+	@Mapping(target = "listVersionID", constant = ERROR_CODE_LIST_VERSION)
+	CodeFehlernummer mapCodeFehlernummer(String code, String name);
+}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/mapper/RequestMapper.java b/src/main/java/de/ozgcloud/xta/test/app/mapper/RequestMapper.java
index d25d9a675256b89a8a39acef593c434d8ed4f51d..b8c7ff6a103d896ff8b295fe34e9313ad929ccd5 100644
--- a/src/main/java/de/ozgcloud/xta/test/app/mapper/RequestMapper.java
+++ b/src/main/java/de/ozgcloud/xta/test/app/mapper/RequestMapper.java
@@ -1,30 +1,35 @@
 package de.ozgcloud.xta.test.app.mapper;
 
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import jakarta.activation.DataHandler;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.Named;
+import org.mapstruct.ReportingPolicy;
+
 import de.ozgcloud.xta.test.app.exception.TechnicalException;
-import de.ozgcloud.xta.test.app.model.Identifier;
+import de.ozgcloud.xta.test.app.model.XtaCloseRequest;
 import de.ozgcloud.xta.test.app.model.XtaFile;
+import de.ozgcloud.xta.test.app.model.XtaGetMessageRequest;
+import de.ozgcloud.xta.test.app.model.XtaIdentifier;
+import de.ozgcloud.xta.test.app.model.XtaLookupServiceRequest;
 import de.ozgcloud.xta.test.app.model.XtaMessage;
 import de.ozgcloud.xta.test.app.model.XtaMessageMetaData;
 import de.ozgcloud.xta.test.app.model.XtaMessageMetaDataListingRequest;
 import genv3.de.xoev.transport.xta.x211.ContentType;
 import genv3.de.xoev.transport.xta.x211.GenericContentContainer;
+import genv3.de.xoev.transport.xta.x211.LookupServiceRequest;
+import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxCloseRequestType;
 import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxFetchRequest;
 import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxStatusListRequestType;
 import genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData;
 import genv3.eu.osci.ws.x2014.x10.transport.PartyIdentifierType;
 import genv3.eu.osci.ws.x2014.x10.transport.PartyType;
 import genv3.eu.osci.ws.x2014.x10.transport.QualifierType;
-import jakarta.activation.DataHandler;
-
-import org.mapstruct.Condition;
-import org.mapstruct.Mapper;
-import org.mapstruct.Mapping;
-import org.mapstruct.Named;
-import org.mapstruct.ReportingPolicy;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
 
 @Mapper(
 		unmappedTargetPolicy = ReportingPolicy.ERROR
@@ -50,24 +55,22 @@ public interface RequestMapper {
 	XtaMessageMetaData mapXtaMessageMetaData(MessageMetaData messageMetaData);
 
 	@Named("mapBusinessScenarioCode")
-	default String mapBusinessScenarioCode(QualifierType.BusinessScenario businessScenario){
+	default String mapBusinessScenarioCode(QualifierType.BusinessScenario businessScenario) {
 		return businessScenario.getDefined() != null ? businessScenario.getDefined().getCode() : businessScenario.getUndefined();
 	}
 
-
 	@Mapping(target = "file", source = "value")
 	@Mapping(target = "name", source = "filename")
 	@Mapping(target = "language", source = "lang")
 	XtaFile mapXtaFileFromContentType(ContentType contentType);
 
-	default File persistToTempFile(DataHandler dataHandler){
+	default File persistToTempFile(DataHandler dataHandler) {
 		try {
 			var file = File.createTempFile("xta", ".data");
 			file.deleteOnExit();
-			var out = new FileOutputStream(file);
-			dataHandler.writeTo(out);
-			out.flush();
-			out.close();
+			try (var out = new FileOutputStream(file)) {
+				dataHandler.writeTo(out);
+			}
 			return file;
 		} catch (IOException e) {
 			throw new TechnicalException("Error writing Attachment to temp file", e);
@@ -78,21 +81,22 @@ public interface RequestMapper {
 		return fetchRequest.getMsgSelector().getMessageID().getFirst().getValue();
 	}
 
-	default int mapMaxListItems(MsgBoxStatusListRequestType fetchRequest){
-		int maxListItems;
-		try{
-			maxListItems = fetchRequest.getMaxListItems().intValueExact();
-		}
-		catch (ArithmeticException e){
-			maxListItems = Integer.MAX_VALUE;
-		}
-		if (maxListItems <= 0){
-			maxListItems = Integer.MAX_VALUE;
-		}
-		return maxListItems;
-	}
-
-	@Mapping(target = "clientIdentifierValue", source = "clientIdentifier.identifier.value")
+	@Mapping(target = "clientIdentifier", source = "clientIdentifier.identifier")
 	@Mapping(target = "maxListItems", source = "fetchRequest.maxListItems")
 	XtaMessageMetaDataListingRequest mapMessageMetaDataListingRequest(MsgBoxStatusListRequestType fetchRequest, PartyType clientIdentifier);
+
+	XtaIdentifier mapXtaIdentifier(PartyIdentifierType partyType);
+
+	@Mapping(target = "messageId", source = "closeRequest.lastMsgReceived.first.value")
+	@Mapping(target = "clientIdentifier", source = "authorIdentifier.identifier")
+	XtaCloseRequest mapXtaCloseRequest(MsgBoxCloseRequestType closeRequest, PartyType authorIdentifier);
+
+	@Mapping(target = "messageId", source = "fetchRequest.msgSelector.messageID.first.value")
+	@Mapping(target = "clientIdentifier", source = "authorIdentifier.identifier")
+	XtaGetMessageRequest mapXtaGetMessageRequest(MsgBoxFetchRequest fetchRequest, PartyType authorIdentifier);
+
+	@Mapping(target = "service", source = "lookupServiceRequest.lookupServiceRequestList.first.lookupService.serviceType")
+	@Mapping(target = "readerIdentifier", source = "lookupServiceRequest.lookupServiceRequestList.first.lookupService.reader.identifier")
+	@Mapping(target = "authorIdentifier", source = "authorIdentifier.identifier")
+	XtaLookupServiceRequest mapXtaLookupServiceRequest(LookupServiceRequest lookupServiceRequest, PartyType authorIdentifier);
 }
diff --git a/src/main/java/de/ozgcloud/xta/test/app/mapper/ResponseMapper.java b/src/main/java/de/ozgcloud/xta/test/app/mapper/ResponseMapper.java
index f7236153c85ac634fbf8c5412759be2ff028bb7e..44b84a51228f55e941a15002a6490afffc2567df 100644
--- a/src/main/java/de/ozgcloud/xta/test/app/mapper/ResponseMapper.java
+++ b/src/main/java/de/ozgcloud/xta/test/app/mapper/ResponseMapper.java
@@ -1,22 +1,18 @@
 package de.ozgcloud.xta.test.app.mapper;
 
-import de.ozgcloud.xta.test.app.model.Identifier;
-import de.ozgcloud.xta.test.app.model.XtaFile;
-import de.ozgcloud.xta.test.app.model.XtaMessage;
-import de.ozgcloud.xta.test.app.model.XtaMessageMetaData;
-import de.ozgcloud.xta.test.app.model.XtaMessageMetaDataListing;
-import genv3.de.xoev.transport.xta.x211.ContentType;
-import genv3.de.xoev.transport.xta.x211.GenericContentContainer;
-import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxResponseType;
-import genv3.eu.osci.ws.x2008.x05.transport.MsgStatusListType;
-import genv3.eu.osci.ws.x2014.x10.transport.KeyCodeType;
-import genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData;
-import genv3.eu.osci.ws.x2014.x10.transport.PartyIdentifierType;
-import genv3.eu.osci.ws.x2014.x10.transport.QualifierType;
+import java.io.File;
+import java.math.BigInteger;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
 
 import jakarta.activation.DataHandler;
 import jakarta.activation.FileDataSource;
 
+import org.apache.cxf.ws.addressing.AttributedURIType;
 import org.mapstruct.Condition;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
@@ -25,9 +21,24 @@ import org.mapstruct.ReportingPolicy;
 import org.mapstruct.SourcePropertyName;
 import org.mapstruct.TargetPropertyName;
 
-import java.io.File;
-import java.math.BigInteger;
-import java.util.List;
+import de.ozgcloud.xta.test.app.model.XtaFile;
+import de.ozgcloud.xta.test.app.model.XtaIdentifier;
+import de.ozgcloud.xta.test.app.model.XtaLookupServiceRequest;
+import de.ozgcloud.xta.test.app.model.XtaMessage;
+import de.ozgcloud.xta.test.app.model.XtaMessageMetaData;
+import de.ozgcloud.xta.test.app.model.XtaMessageMetaDataListing;
+import genv3.de.xoev.transport.xta.x211.ContentType;
+import genv3.de.xoev.transport.xta.x211.GenericContentContainer;
+import genv3.de.xoev.transport.xta.x211.LookupServiceResponse;
+import genv3.de.xoev.transport.xta.x211.LookupServiceResultType;
+import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxResponseType;
+import genv3.eu.osci.ws.x2008.x05.transport.MsgStatusListType;
+import genv3.eu.osci.ws.x2014.x10.transport.DeliveryAttributesType;
+import genv3.eu.osci.ws.x2014.x10.transport.KeyCodeType;
+import genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData;
+import genv3.eu.osci.ws.x2014.x10.transport.PartyIdentifierType;
+import genv3.eu.osci.ws.x2014.x10.transport.QualifierType;
+import lombok.SneakyThrows;
 
 @Mapper(
 		unmappedTargetPolicy = ReportingPolicy.ERROR,
@@ -39,18 +50,24 @@ public interface ResponseMapper {
 	String MESSAGE_TYPE_LIST_VERSION_ID = "1.0";
 	String REQUEST_ID = "1";
 	String NO_MESSAGES_REASON = "Keine Nachrichten gefunden.";
+	XtaIdentifier SENDER_IDENTIFIER = XtaIdentifier.builder()
+			.name("xta-test-server")
+			.value("xta-test-server")
+			.category("dbs:testumgebung")
+			.build();
 
 	@Mapping(target = "qualifier.service", source = "service")
 	@Mapping(target = "qualifier.businessScenario", source = ".", qualifiedByName = "mapBusinessScenario")
 	@Mapping(target = "qualifier.messageType", source = ".")
 	@Mapping(target = "msgIdentification.messageID.value", source = "messageId")
 	@Mapping(target = "originators.author.identifier", source = "authorIdentifier")
+	@Mapping(target = "originators.sender.identifier", expression = "java( mapPartyIdentifierType(SENDER_IDENTIFIER) )")
 	@Mapping(target = "destinations.reader.identifier", source = "readerIdentifier")
 	@Mapping(target = "msgSize", source = "messageSize")
 	@Mapping(target = "testMsg", ignore = true)
-	@Mapping(target = "deliveryAttributes", ignore = true)
+	@Mapping(target = "deliveryAttributes", expression = "java( createDefaultDeliveryAttributes(createNowXmlGregorianCalendarFromLocalDateTime()) )")
 	@Mapping(target = "messageProperties", ignore = true)
-	MessageMetaData mapMessageMetaDataFromXtaMessageMetaData(XtaMessageMetaData xtaMessageMetaData);
+	MessageMetaData mapMessageMetaData(XtaMessageMetaData xtaMessageMetaData);
 
 	@Named("mapBusinessScenario")
 	default QualifierType.BusinessScenario mapBusinessScenario(XtaMessageMetaData xtaMessageMetaData) {
@@ -81,7 +98,7 @@ public interface ResponseMapper {
 	QualifierType.MessageType mapMessageTypeQualifierType(XtaMessageMetaData xtaMessageMetaData);
 
 	@Mapping(target = "type", constant = IDENTIFIER_TYPE)
-	PartyIdentifierType mapPartyIdentifierType(Identifier value);
+	PartyIdentifierType mapPartyIdentifierType(XtaIdentifier value);
 
 	@Mapping(target = "encryptedData", expression = "java(null)")
 	@Mapping(target = "contentContainer.message", source = "messageFile")
@@ -98,10 +115,27 @@ public interface ResponseMapper {
 		return new DataHandler(dataSource);
 	}
 
+	@Mapping(target = "delivery", source = ".")
+	@Mapping(target = "initialFetch", source = ".")
+	@Mapping(target = "initialSend", source = ".")
+	@Mapping(target = "origin", source = ".")
+	@Mapping(target = "notBefore", ignore = true)
+	@Mapping(target = "obsoleteAfter", ignore = true)
+	@Mapping(target = "reception", ignore = true)
+	@Mapping(target = "serviceQuality", ignore = true)
+	@Mapping(target = "receiptRequests", ignore = true)
+	DeliveryAttributesType createDefaultDeliveryAttributes(XMLGregorianCalendar timestamp);
+
+	@SneakyThrows
+	default XMLGregorianCalendar createNowXmlGregorianCalendarFromLocalDateTime() {
+		var isoTimeString = DateTimeFormatter.ISO_DATE_TIME.format(LocalDateTime.now());
+		return DatatypeFactory.newInstance().newXMLGregorianCalendar(isoTimeString);
+	}
+
 	@Mapping(target = "itemsPending", expression = "java( BigInteger.ZERO )")
 	@Mapping(target = "msgBoxRequestID", source = "requestId")
 	@Mapping(target = "noMessageAvailable", expression = "java( null )")
-	MsgBoxResponseType mapMsgBoxResponseTypeFromRequestID(String requestId);
+	MsgBoxResponseType mapMsgBoxResponseTypeFromRequestId(String requestId);
 
 	@Mapping(target = "itemsPending", source = "pendingMessageCount")
 	@Mapping(target = "msgBoxRequestID", constant = REQUEST_ID)
@@ -133,4 +167,16 @@ public interface ResponseMapper {
 	@Mapping(target = "itemsPending", ignore = true)
 	@Mapping(target = "noMessageAvailable.reason", source = "errorString")
 	MsgBoxResponseType mapMsgBoxResponseTypeError(String errorString);
+
+	@Mapping(target = "isServiceAvailableValue.serviceIsAvailable", expression = "java( true )")
+	@Mapping(target = "serviceType", source = "service")
+	@Mapping(target = "reader.identifier", source = "readerIdentifier")
+	@Mapping(target = "serviceParameter", ignore = true)
+	LookupServiceResultType mapLookupServiceResultType(XtaLookupServiceRequest xtaLookupServiceRequest);
+
+	@Mapping(target = "lookupServiceResultList.lookupServiceResult", expression = "java( List.of( mapLookupServiceResultType(xtaLookupServiceRequest) ) )")
+	LookupServiceResponse mapLookupServiceResponse(XtaLookupServiceRequest xtaLookupServiceRequest);
+
+	@Mapping(target = "otherAttributes", ignore = true)
+	AttributedURIType mapCreateMessageIdResponse(String value);
 }
diff --git a/src/main/java/de/ozgcloud/xta/test/app/model/ProtocolMetadata.java b/src/main/java/de/ozgcloud/xta/test/app/model/ProtocolMetadata.java
deleted file mode 100644
index 9fd11cd7bc515e222e1c2df9887fce39383d9ab5..0000000000000000000000000000000000000000
--- a/src/main/java/de/ozgcloud/xta/test/app/model/ProtocolMetadata.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * @formatter:off
- *
- * Copyright 2021-2022  Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the European Public License, Version 1.2 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     https://opensource.org/licenses/EUPL-1.2
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * @formatter:on
- */
-package de.ozgcloud.xta.test.app.model;
-
-import java.util.Collections;
-import java.util.List;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-@Data
-@NoArgsConstructor
-public class ProtocolMetadata {
-
-	private String softwareManufacturer = "Nortal AG";
-	private String softwareName = "Dummy Produkt";
-	private String softwareVersion = "1.0.0";
-
-	private String street = "Knesebeckstraße";
-	private String streetNo = "1";
-	private String zipCode = "10623";
-	private String city = "Berlin";
-	private String addressAddition;
-
-	@JsonIgnore
-	public List<String> getAddressAdditionAsList() {
-		if (addressAddition != null) {
-			String[] split = addressAddition.split("\r\n|\n|\r");
-			return List.of(split);
-		}
-		return Collections.emptyList();
-	}
-}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/model/XtaCloseRequest.java b/src/main/java/de/ozgcloud/xta/test/app/model/XtaCloseRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..d6d2ac2b43b6d109fc81c4781543c3557b98359b
--- /dev/null
+++ b/src/main/java/de/ozgcloud/xta/test/app/model/XtaCloseRequest.java
@@ -0,0 +1,17 @@
+package de.ozgcloud.xta.test.app.model;
+
+import static de.ozgcloud.xta.test.app.validation.ValidXtaId.*;
+
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+
+import de.ozgcloud.xta.test.app.validation.ValidXtaId;
+import lombok.Builder;
+
+@Builder
+public record XtaCloseRequest(
+		@ValidXtaId(namespace = MESSAGE_ID_NAMESPACE) String messageId,
+		@NotNull @Valid XtaIdentifier clientIdentifier
+) {
+}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/model/XtaConfigDto.java b/src/main/java/de/ozgcloud/xta/test/app/model/XtaConfigDto.java
deleted file mode 100644
index c74cdcc4c81870abe4e12787eaa2f68adbf9c717..0000000000000000000000000000000000000000
--- a/src/main/java/de/ozgcloud/xta/test/app/model/XtaConfigDto.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Created 2022-12-14
- */
-package de.ozgcloud.xta.test.app.model;
-
-import de.ozgcloud.xta.test.app.config.ClientProperties;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-@Data
-@NoArgsConstructor
-
-public class XtaConfigDto {
-
-	private ProtocolMetadata protocolMetadata;
-
-	private ClientProperties clientProperties;
-}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/model/XtaConstants.java b/src/main/java/de/ozgcloud/xta/test/app/model/XtaConstants.java
deleted file mode 100644
index a5af9770da236f89a773991a477349bb17c84c30..0000000000000000000000000000000000000000
--- a/src/main/java/de/ozgcloud/xta/test/app/model/XtaConstants.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * @formatter:off
- *
- * Copyright 2021-2022  Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the European Public License, Version 1.2 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     https://opensource.org/licenses/EUPL-1.2
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * @formatter:on
- */
-package de.ozgcloud.xta.test.app.model;
-
-import javax.xml.namespace.QName;
-
-import lombok.experimental.UtilityClass;
-
-@UtilityClass
-public class XtaConstants {
-
-	public static final String W3_ORG_2005_08_ADDRESSING = "http://www.w3.org/2005/08/addressing";
-
-	public static final String XTA_211 = "http://xoev.de/transport/xta/211";
-	public static final String XTA_ACTION_BASE = "http://www.xta.de/XTA/";
-
-	public static final String OSCI_2008_05_TRANSPORT = "http://www.osci.eu/ws/2008/05/transport";
-	public static final String OSCI_2014_10_TRANSPORT = "http://www.osci.eu/ws/2014/10/transport";
-
-	public static final String OSCI_2008_05_ACTION_BASE = OSCI_2008_05_TRANSPORT + "/urn/messageTypes/";
-	public static final String OSCI_2014_10_ACTION_BASE = OSCI_2014_10_TRANSPORT + "/urn/messageTypes/";
-
-	/*
-	 * Xml QNames in alphabetic order
-	 */
-
-	public static final QName ACTION = new QName(W3_ORG_2005_08_ADDRESSING, "Action");
-	public static final QName MSG_BOX_RESPONSE = new QName(OSCI_2008_05_TRANSPORT, "MsgBoxResponse");
-	public static final QName MESSAGE_META_DATA = new QName(OSCI_2014_10_TRANSPORT, "MessageMetaData");
-	public static final QName TO = new QName(W3_ORG_2005_08_ADDRESSING, "To");
-
-	/*
-	 * Actions in alphabetic order
-	 */
-
-	public static final String CANCEL_MESSAGE_ACTION = XTA_ACTION_BASE + "CancelMessage";
-	public static final String CHECK_ACCOUNT_ACTIVE_ACTION = XTA_ACTION_BASE + "CheckAccountActive";
-	public static final String CLOSE_ACTION = OSCI_2008_05_ACTION_BASE + "MsgBoxCloseRequest";
-	public static final String CREATE_MESSAGE_ID_ACTION = XTA_ACTION_BASE + "CreateMessageID";
-
-	public static final String GET_MESSAGE_ACTION = OSCI_2008_05_ACTION_BASE + "MsgBoxFetchRequest";
-	public static final String GET_NEXT_MESSAGE_ACTION = OSCI_2008_05_ACTION_BASE + "MsgBoxGetNextMsgRequest";
-	public static final String GET_NEXT_STATUS_LIST_ACTION = OSCI_2008_05_ACTION_BASE + "MsgBoxGetNextListRequest";
-	public static final String GET_STATUS_LIST_ACTION = OSCI_2008_05_ACTION_BASE + "MsgBoxStatusListRequest";
-	public static final String GET_TRANSPORT_REPORT_ACTION = XTA_ACTION_BASE + "GetTransportReport";
-
-	public static final String LOOKUP_SERVICE_ACTION = XTA_ACTION_BASE + "IsServiceAvailable";
-
-	public static final String SEND_MESSAGE_ACTION = XTA_ACTION_BASE + "SendMessage";
-	public static final String SEND_MESSAGE_SYNC_ACTION = XTA_ACTION_BASE + "SendMessageSync";
-
-	public enum ConnectionPortType {
-		SEND, MSGBOX, MANAGEMENT
-	}
-}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/model/XtaGetMessageRequest.java b/src/main/java/de/ozgcloud/xta/test/app/model/XtaGetMessageRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..443a9c61edb79faefd74efeea7800f88ee07a14c
--- /dev/null
+++ b/src/main/java/de/ozgcloud/xta/test/app/model/XtaGetMessageRequest.java
@@ -0,0 +1,17 @@
+package de.ozgcloud.xta.test.app.model;
+
+import static de.ozgcloud.xta.test.app.validation.ValidXtaId.*;
+
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+
+import de.ozgcloud.xta.test.app.validation.ValidXtaId;
+import lombok.Builder;
+
+@Builder
+public record XtaGetMessageRequest(
+		@ValidXtaId(namespace = MESSAGE_ID_NAMESPACE) String messageId,
+		@NotNull @Valid XtaIdentifier clientIdentifier
+) {
+}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/model/Identifier.java b/src/main/java/de/ozgcloud/xta/test/app/model/XtaIdentifier.java
similarity index 89%
rename from src/main/java/de/ozgcloud/xta/test/app/model/Identifier.java
rename to src/main/java/de/ozgcloud/xta/test/app/model/XtaIdentifier.java
index 22c681c8b801ea46d97c5f2ca42bc3b06a07b4e6..524d8e0d1c8e803be503704884e1c309c06416f5 100644
--- a/src/main/java/de/ozgcloud/xta/test/app/model/Identifier.java
+++ b/src/main/java/de/ozgcloud/xta/test/app/model/XtaIdentifier.java
@@ -6,7 +6,7 @@ import jakarta.validation.constraints.NotBlank;
 import lombok.Builder;
 
 @Builder
-public record Identifier(
+public record XtaIdentifier(
 		@Nullable String name,
 		@Nullable String category,
 		@NotBlank String value
diff --git a/src/main/java/de/ozgcloud/xta/test/app/model/XtaIdentifierConfig.java b/src/main/java/de/ozgcloud/xta/test/app/model/XtaIdentifierConfig.java
deleted file mode 100644
index d8c4c8a4dbf83c86e66b85c1a008094a47713b9a..0000000000000000000000000000000000000000
--- a/src/main/java/de/ozgcloud/xta/test/app/model/XtaIdentifierConfig.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package de.ozgcloud.xta.test.app.model;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-public class XtaIdentifierConfig {
-
-	private String identifierScheme;
-
-	private String name;
-
-	private String value;
-
-	private String organizationCategory;
-
-}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/model/XtaLookupServiceRequest.java b/src/main/java/de/ozgcloud/xta/test/app/model/XtaLookupServiceRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..ab46e3b2f1c9d0b41d0bf498a0a0c35c15c10b4d
--- /dev/null
+++ b/src/main/java/de/ozgcloud/xta/test/app/model/XtaLookupServiceRequest.java
@@ -0,0 +1,15 @@
+package de.ozgcloud.xta.test.app.model;
+
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+
+import lombok.Builder;
+
+@Builder
+public record XtaLookupServiceRequest(
+		@NotBlank String service,
+		@NotNull @Valid XtaIdentifier readerIdentifier,
+		@NotNull @Valid XtaIdentifier authorIdentifier
+) {
+}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/model/XtaMessageMetaData.java b/src/main/java/de/ozgcloud/xta/test/app/model/XtaMessageMetaData.java
index e48bf9962d1303af0170afcd07cf40cd62bb4349..458ee204f855a675ccd767a58960d643fea7286a 100644
--- a/src/main/java/de/ozgcloud/xta/test/app/model/XtaMessageMetaData.java
+++ b/src/main/java/de/ozgcloud/xta/test/app/model/XtaMessageMetaData.java
@@ -1,5 +1,7 @@
 package de.ozgcloud.xta.test.app.model;
 
+import static de.ozgcloud.xta.test.app.validation.ValidXtaId.*;
+
 import java.math.BigInteger;
 
 import jakarta.annotation.Nullable;
@@ -8,20 +10,21 @@ import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
 import jakarta.validation.constraints.PositiveOrZero;
 
+import de.ozgcloud.xta.test.app.validation.ValidXtaId;
 import lombok.Builder;
 
 @Builder(toBuilder = true)
 public record XtaMessageMetaData(
 		@NotBlank String service,
-		@NotNull @NotBlank String businessScenarioCode,
+		@NotBlank String businessScenarioCode,
 		@Nullable String businessScenarioName,
 		@Nullable String businessScenarioListUri,
 		@Nullable String businessScenarioListVersionId,
 		@NotBlank String messageTypeCode,
 		@NotBlank String messageTypePayloadSchema,
-		@NotBlank String messageId,
-		@NotNull @Valid Identifier authorIdentifier,
-		@NotNull @Valid Identifier readerIdentifier,
+		@ValidXtaId(namespace = MESSAGE_ID_NAMESPACE) String messageId,
+		@NotNull @Valid XtaIdentifier authorIdentifier,
+		@NotNull @Valid XtaIdentifier readerIdentifier,
 		@PositiveOrZero BigInteger messageSize
 ) {
 }
diff --git a/src/main/java/de/ozgcloud/xta/test/app/model/XtaMessageMetaDataListing.java b/src/main/java/de/ozgcloud/xta/test/app/model/XtaMessageMetaDataListing.java
index 72f1977c4b282334d6acccef5a0230b29997f381..d4c37bbd5e02657821b9db740f695051368c4156 100644
--- a/src/main/java/de/ozgcloud/xta/test/app/model/XtaMessageMetaDataListing.java
+++ b/src/main/java/de/ozgcloud/xta/test/app/model/XtaMessageMetaDataListing.java
@@ -4,7 +4,6 @@ import java.math.BigInteger;
 import java.util.List;
 
 import jakarta.validation.Valid;
-import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
 import jakarta.validation.constraints.PositiveOrZero;
 
@@ -12,7 +11,7 @@ import lombok.Builder;
 
 @Builder
 public record XtaMessageMetaDataListing(
-		@NotNull @PositiveOrZero BigInteger pendingMessageCount,
-		@NotNull @Valid List<XtaMessageMetaData> messages
+		@PositiveOrZero BigInteger pendingMessageCount,
+		@NotNull List<@Valid XtaMessageMetaData> messages
 ) {
 }
diff --git a/src/main/java/de/ozgcloud/xta/test/app/model/XtaMessageMetaDataListingRequest.java b/src/main/java/de/ozgcloud/xta/test/app/model/XtaMessageMetaDataListingRequest.java
index 279014fb4fe85325d03b34115d211f87eebadc8a..c19441db3217c06ae165f976cf914d3af69b1622 100644
--- a/src/main/java/de/ozgcloud/xta/test/app/model/XtaMessageMetaDataListingRequest.java
+++ b/src/main/java/de/ozgcloud/xta/test/app/model/XtaMessageMetaDataListingRequest.java
@@ -1,13 +1,15 @@
 package de.ozgcloud.xta.test.app.model;
 
+import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
 import jakarta.validation.constraints.Positive;
 
 import lombok.Builder;
 
 @Builder
 public record XtaMessageMetaDataListingRequest(
-		@NotBlank String clientIdentifierValue,
+		@NotNull @Valid XtaIdentifier clientIdentifier,
 		@Positive int maxListItems
 ) {
 }
diff --git a/src/main/java/de/ozgcloud/xta/test/app/server/ManagementPortImpl.java b/src/main/java/de/ozgcloud/xta/test/app/server/ManagementPortImpl.java
index bf1dec6a9b3f87873eef523c57b7fa04d22fd617..d47d13465fa68e0f1db6e523a19a77e27e847b5a 100644
--- a/src/main/java/de/ozgcloud/xta/test/app/server/ManagementPortImpl.java
+++ b/src/main/java/de/ozgcloud/xta/test/app/server/ManagementPortImpl.java
@@ -1,39 +1,24 @@
 package de.ozgcloud.xta.test.app.server;
 
-import java.io.IOException;
-import java.math.BigInteger;
-import java.util.List;
-
-import jakarta.activation.DataHandler;
 import jakarta.annotation.Generated;
 import jakarta.jws.WebService;
 
 import org.apache.cxf.annotations.SchemaValidation;
 import org.apache.cxf.ws.addressing.AttributedURIType;
-import org.springframework.core.io.ClassPathResource;
 import org.springframework.stereotype.Component;
 
-import de.ozgcloud.xta.test.app.service.ParameterValidatorService;
-import de.ozgcloud.xta.test.app.service.XtaParameter;
-import de.ozgcloud.xta.test.app.util.XtaIdGenerator;
-import genv3.de.xoev.transport.xta.x211.AdditionalReportListType;
-import genv3.de.xoev.transport.xta.x211.AdditionalReportListType.Report;
+import de.ozgcloud.xta.test.app.mapper.RequestMapper;
+import de.ozgcloud.xta.test.app.mapper.ResponseMapper;
+import de.ozgcloud.xta.test.app.service.XtaMessageService;
+import de.ozgcloud.xta.test.app.validation.RequestValidator;
 import genv3.de.xoev.transport.xta.x211.CancelDeniedException;
-import genv3.de.xoev.transport.xta.x211.CodeReportType;
 import genv3.de.xoev.transport.xta.x211.InvalidMessageIDException;
-import genv3.de.xoev.transport.xta.x211.IsServiceAvailableValueType;
 import genv3.de.xoev.transport.xta.x211.LookupServiceRequest;
-import genv3.de.xoev.transport.xta.x211.LookupServiceRequest.LookupServiceRequestList;
-import genv3.de.xoev.transport.xta.x211.LookupServiceResponse;
-import genv3.de.xoev.transport.xta.x211.LookupServiceResponse.LookupServiceResultList;
-import genv3.de.xoev.transport.xta.x211.LookupServiceResultType;
 import genv3.de.xoev.transport.xta.x211.ManagementPortType;
 import genv3.de.xoev.transport.xta.x211.ParameterIsNotValidException;
 import genv3.de.xoev.transport.xta.x211.PermissionDeniedException;
 import genv3.de.xoev.transport.xta.x211.TransportReport;
 import genv3.de.xoev.transport.xta.x211.XTAWSTechnicalProblemException;
-import genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData;
-import genv3.eu.osci.ws.x2014.x10.transport.PartyType;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
 
@@ -44,8 +29,10 @@ import lombok.extern.log4j.Log4j2;
 @Log4j2
 public class ManagementPortImpl implements ManagementPortType {
 
-	private final ParameterValidatorService validator;
-
+	private final ResponseMapper responseMapper;
+	private final RequestMapper requestMapper;
+	private final RequestValidator requestValidator;
+	private final XtaMessageService xtaMessageService;
 
 	/*
 	 * (non-Javadoc)
@@ -57,9 +44,10 @@ public class ManagementPortImpl implements ManagementPortType {
 			final genv3.eu.osci.ws.x2014.x10.transport.PartyType authorIdentifier)
 			throws XTAWSTechnicalProblemException, PermissionDeniedException {
 		log.info("Executing operation createMessageId");
-		AttributedURIType messageId = new AttributedURIType();
-		messageId.setValue(XtaIdGenerator.generateMessageId().toString());
-		return messageId;
+
+		return responseMapper.mapCreateMessageIdResponse(
+				xtaMessageService.createMessageId()
+		);
 	}
 
 	/*
@@ -86,30 +74,10 @@ public class ManagementPortImpl implements ManagementPortType {
 			final genv3.eu.osci.ws.x2014.x10.transport.PartyType authorIdentifier)
 			throws XTAWSTechnicalProblemException, PermissionDeniedException, ParameterIsNotValidException {
 		log.info("Executing operation lookupService");
+		var request = requestMapper.mapXtaLookupServiceRequest(lookupServiceRequest, authorIdentifier);
+		requestValidator.validate(request);
 
-		LookupServiceResponse lookupResponse = new LookupServiceResponse();
-
-		LookupServiceResultList lookupServiceResultList = new LookupServiceResultList();
-		lookupResponse.setLookupServiceResultList(lookupServiceResultList);
-		List<LookupServiceResultType> resultlist = lookupServiceResultList.getLookupServiceResult();
-
-		for (LookupServiceRequestList lookupServiceRequestList : lookupServiceRequest.getLookupServiceRequestList()) {
-
-			LookupServiceResultType lookupServiceResult = new LookupServiceResultType();
-			resultlist.add(lookupServiceResult);
-			IsServiceAvailableValueType serviceAvailable = new IsServiceAvailableValueType();
-			lookupServiceResult.setIsServiceAvailableValue(serviceAvailable);
-			serviceAvailable.setServiceIsAvailable(true);
-
-			PartyType requestReader = lookupServiceRequestList.getLookupService().getReader();
-			PartyType reader = new PartyType();
-			lookupServiceResult.setReader(reader);
-			reader.setIdentifier(requestReader.getIdentifier());
-			reader.getSecurityToken().addAll(requestReader.getSecurityToken());
-
-			lookupServiceResult.setServiceType(lookupServiceRequestList.getLookupService().getServiceType());
-		}
-		return lookupResponse;
+		return responseMapper.mapLookupServiceResponse(request);
 	}
 
 	/*
@@ -124,8 +92,7 @@ public class ManagementPortImpl implements ManagementPortType {
 			throws XTAWSTechnicalProblemException, CancelDeniedException, PermissionDeniedException,
 			ParameterIsNotValidException {
 		log.info("Executing operation cancelMessage");
-		log.info("cancelMessage called, author: {}", authorIdentifier);
-
+		throw new XTAWSTechnicalProblemException("Method not supported");
 	}
 
 	/*
@@ -140,7 +107,6 @@ public class ManagementPortImpl implements ManagementPortType {
 			final genv3.eu.osci.ws.x2014.x10.transport.PartyType authorIdentifier)
 			throws XTAWSTechnicalProblemException, InvalidMessageIDException, PermissionDeniedException {
 		log.info("Executing operation getTransportReport");
-		validator.isNotBlank(messageID.getValue(), XtaParameter.MESSAGE_ID);
 		TransportReport transportReport = new TransportReport();
 
 		// TODO implement
diff --git a/src/main/java/de/ozgcloud/xta/test/app/server/MsgBoxPortImpl.java b/src/main/java/de/ozgcloud/xta/test/app/server/MsgBoxPortImpl.java
index 1a09fc673537234386c0f4a91c54dd0ec30d3440..6e43533453efffd463ccef3c380f5d33b2136fc3 100644
--- a/src/main/java/de/ozgcloud/xta/test/app/server/MsgBoxPortImpl.java
+++ b/src/main/java/de/ozgcloud/xta/test/app/server/MsgBoxPortImpl.java
@@ -1,28 +1,19 @@
 package de.ozgcloud.xta.test.app.server;
 
-import java.util.Optional;
-
 import jakarta.jws.WebService;
 
 import org.apache.cxf.annotations.SchemaValidation;
-import org.apache.cxf.ws.addressing.AttributedURIType;
 import org.springframework.stereotype.Component;
 
-import de.ozgcloud.xta.test.app.model.XtaMessage;
-import de.ozgcloud.xta.test.app.service.ParameterValidatorService;
+import de.ozgcloud.xta.test.app.mapper.ExceptionMapper;
 import de.ozgcloud.xta.test.app.mapper.RequestMapper;
 import de.ozgcloud.xta.test.app.mapper.ResponseMapper;
 import de.ozgcloud.xta.test.app.service.XtaMessageService;
-import de.ozgcloud.xta.test.app.service.XtaParameter;
-import de.ozgcloud.xta.test.app.util.XtaIdGenerator;
+import de.ozgcloud.xta.test.app.validation.RequestValidator;
 import genv3.de.xoev.transport.xta.x211.InvalidMessageIDException;
 import genv3.de.xoev.transport.xta.x211.MsgBoxPortType;
 import genv3.de.xoev.transport.xta.x211.PermissionDeniedException;
 import genv3.de.xoev.transport.xta.x211.XTAWSTechnicalProblemException;
-import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxFetchRequest;
-import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxStatusListRequestType;
-import genv3.eu.osci.ws.x2008.x05.transport.MsgSelector;
-import genv3.eu.osci.ws.x2008.x05.transport.MsgStatusListType;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
 
@@ -33,9 +24,9 @@ import lombok.extern.log4j.Log4j2;
 @Log4j2
 public class MsgBoxPortImpl implements MsgBoxPortType {
 
-	private final ParameterValidatorService validator;
-
+	private final RequestValidator requestValidator;
 	private final RequestMapper requestMapper;
+	private final ExceptionMapper exceptionMapper;
 	private final ResponseMapper responseMapper;
 	private final XtaMessageService messageService;
 
@@ -55,44 +46,19 @@ public class MsgBoxPortImpl implements MsgBoxPortType {
 			throws XTAWSTechnicalProblemException, InvalidMessageIDException, PermissionDeniedException {
 		log.info("Executing operation getMessage");
 
-		validateFetchRequest(fetchRequest);
+		var request = requestMapper.mapXtaGetMessageRequest(fetchRequest, authorIdentifier);
+		requestValidator.validate(request);
 
-		String messageId = requestMapper.mapMessageIdFromMsgBoxFetchRequest(fetchRequest);
-		XtaMessage message = getXtaMessageOrThrow(messageId);
-		String msgBoxRequestId = XtaIdGenerator.generateRequestId().toString();
+		var message = messageService.getMessage(request)
+				.orElseThrow(() -> createInvalidMessageIdException(request.messageId(), request.clientIdentifier().value()));
 
-		messageMetaData.value = responseMapper.mapMessageMetaDataFromXtaMessageMetaData(message.metaData());
-		fetchResponseHeader.value = responseMapper.mapMsgBoxResponseTypeFromRequestID(msgBoxRequestId);
+		messageMetaData.value = responseMapper.mapMessageMetaData(message.metaData());
+		fetchResponseHeader.value = responseMapper.mapMsgBoxResponseTypeFromRequestId(
+				messageService.createRequestId()
+		);
 		return responseMapper.mapGenericContentContainerFromXtaMessage(message);
 	}
 
-	private void validateFetchRequest(MsgBoxFetchRequest fetchRequest) throws XTAWSTechnicalProblemException {
-		if (!(validator.isNotNull(fetchRequest.getMsgPart(), "MsgPart")
-				&& checkMessageSelectionSupported(fetchRequest.getMsgSelector())
-				&& validator.isListSizeEquals(fetchRequest.getMsgSelector().getMessageID(), 1, "MessageID"))) {
-			throw new XTAWSTechnicalProblemException("Invalid fetch request");
-		}
-	}
-
-	private boolean checkMessageSelectionSupported(MsgSelector msgSelector) {
-		// Selection only by messageID is required
-		return msgSelector != null
-				&& msgSelector.isNewEntry() == null
-				&& msgSelector.getMsgBoxEntryTimeFrom() == null
-				&& msgSelector.getMsgBoxEntryTimeTo() == null
-				&& msgSelector.getMessageID() != null
-				&& msgSelector.getRelatesTo() == null
-				&& msgSelector.getExtension() == null;
-	}
-
-	private XtaMessage getXtaMessageOrThrow(String messageId) throws InvalidMessageIDException {
-		Optional<XtaMessage> message = messageService.getMessage(messageId);
-		if (message.isEmpty()) {
-			throw new InvalidMessageIDException("No message with messageID \"" + messageId + "\" available.");
-		}
-		return message.get();
-	}
-
 	/*
 	 * (non-Javadoc)
 	 * @see genv3.de.xoev.transport.xta.x211.MsgBoxPortType#getStatusList(genv3.eu.osci.ws.x2008.x05.transport.
@@ -106,29 +72,16 @@ public class MsgBoxPortImpl implements MsgBoxPortType {
 			final jakarta.xml.ws.Holder<genv3.eu.osci.ws.x2008.x05.transport.MsgBoxResponseType> msgBoxResponseHeader)
 			throws XTAWSTechnicalProblemException, PermissionDeniedException {
 		log.info("Executing operation getStatusList");
-		validateGetStatusListRequest(statusListRequest);
-
-		if (validator.isNotNull(statusListRequest.getMsgSelector(), "msgSelector")) {
-			msgBoxResponseHeader.value = responseMapper.mapMsgBoxResponseTypeError(
-					"SearchArgsInvalid: This test server doesn't support message selection in the 'getStatusList' operation.");
-			return new MsgStatusListType();
-		}
 
 		var request = requestMapper.mapMessageMetaDataListingRequest(statusListRequest, authorIdentifier);
+		requestValidator.validate(request);
+
 		var listing = messageService.getStatusList(request);
+
 		msgBoxResponseHeader.value = responseMapper.mapMsgBoxResponseType(listing);
 		return responseMapper.mapMsgStatusListType(listing);
 	}
 
-
-	private void validateGetStatusListRequest(MsgBoxStatusListRequestType statusListRequest) throws XTAWSTechnicalProblemException {
-		if (!(
-				validator.isNotNull(statusListRequest.getListForm(), "listForm")
-						&& validator.isNotNull(statusListRequest.getMaxListItems(), "maxListItems"))) {
-			throw new XTAWSTechnicalProblemException("Invalid getStatusList request");
-		}
-	}
-
 	/*
 	 * (non-Javadoc)
 	 * @see genv3.de.xoev.transport.xta.x211.MsgBoxPortType#getNextMessage(genv3.eu.osci.ws.x2008.x05.transport.
@@ -174,10 +127,18 @@ public class MsgBoxPortImpl implements MsgBoxPortType {
 			final genv3.eu.osci.ws.x2014.x10.transport.PartyType authorIdentifier)
 			throws XTAWSTechnicalProblemException, InvalidMessageIDException, PermissionDeniedException {
 		log.info("Executing operation close");
-		for (AttributedURIType messageId : closeRequest.getLastMsgReceived()) {
-			validator.isNotBlank(messageId.getValue(), XtaParameter.MESSAGE_ID);
-			messageService.closeMessage(messageId.getValue());
+		var request = requestMapper.mapXtaCloseRequest(closeRequest, authorIdentifier);
+		requestValidator.validate(request);
+
+		if (!messageService.closeMessage(request)) {
+			throw createInvalidMessageIdException(request.messageId(), request.clientIdentifier().value());
 		}
 	}
 
+	private InvalidMessageIDException createInvalidMessageIdException(String messageId, String clientIdentifierValue) {
+		return exceptionMapper.createInvalidMessageIDException(
+				"No message with messageID \"%s\" available for identifier \"%s\"."
+						.formatted(messageId, clientIdentifierValue));
+	}
+
 }
diff --git a/src/main/java/de/ozgcloud/xta/test/app/server/SendXtaPortImpl.java b/src/main/java/de/ozgcloud/xta/test/app/server/SendXtaPortImpl.java
index c769881a9cf8e11b78b5d0d52ae7ac159af6aa58..81832a0ea7612621dcc2d123e9470e128c22a0fd 100644
--- a/src/main/java/de/ozgcloud/xta/test/app/server/SendXtaPortImpl.java
+++ b/src/main/java/de/ozgcloud/xta/test/app/server/SendXtaPortImpl.java
@@ -1,13 +1,14 @@
 package de.ozgcloud.xta.test.app.server;
 
-import de.ozgcloud.xta.test.app.mapper.RequestMapper;
-import genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData;
-import lombok.RequiredArgsConstructor;
+import jakarta.jws.WebService;
+
 import org.apache.cxf.annotations.SchemaValidation;
 import org.springframework.stereotype.Component;
 
-import de.ozgcloud.xta.test.app.service.ParameterValidatorService;
+import de.ozgcloud.xta.test.app.mapper.ExceptionMapper;
+import de.ozgcloud.xta.test.app.mapper.RequestMapper;
 import de.ozgcloud.xta.test.app.service.XtaMessageService;
+import de.ozgcloud.xta.test.app.validation.RequestValidator;
 import genv3.de.xoev.transport.xta.x211.GenericContentContainer;
 import genv3.de.xoev.transport.xta.x211.MessageSchemaViolationException;
 import genv3.de.xoev.transport.xta.x211.MessageVirusDetectionException;
@@ -16,7 +17,7 @@ import genv3.de.xoev.transport.xta.x211.PermissionDeniedException;
 import genv3.de.xoev.transport.xta.x211.SendPortType;
 import genv3.de.xoev.transport.xta.x211.SyncAsyncException;
 import genv3.de.xoev.transport.xta.x211.XTAWSTechnicalProblemException;
-import jakarta.jws.WebService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
 
 @WebService(serviceName = "XTAService", portName = "SendXtaPort", targetNamespace = "http://xoev.de/transport/xta/211", wsdlLocation = "classpath:wsdl/XTA.wsdl", endpointInterface = "genv3.de.xoev.transport.xta.x211.SendPortType")
@@ -26,54 +27,47 @@ import lombok.extern.log4j.Log4j2;
 @Log4j2
 public class SendXtaPortImpl implements SendPortType {
 
-    private final ParameterValidatorService validator;
-
-    private final RequestMapper requestMapper;
-    private final XtaMessageService xtaMessageService;
+	private final RequestValidator validator;
 
-    /*
-     * (non-Javadoc)
-     * @see genv3.de.xoev.transport.xta.x211.SendPortType#sendMessage(genv3.de.xoev.transport.xta.x211.
-     * GenericContentContainer genericContainer, genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData messageMetaData,
-     * genv3.eu.osci.ws.x2008.x05.transport.X509TokenContainerType x509TokenContainer)*
-     */
-    @Override
-    public void sendMessage(final GenericContentContainer genericContainer,
-            final genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData messageMetaData,
-            final genv3.eu.osci.ws.x2008.x05.transport.X509TokenContainerType x509TokenContainer)
-            throws SyncAsyncException, XTAWSTechnicalProblemException, MessageVirusDetectionException,
-            MessageSchemaViolationException, PermissionDeniedException, ParameterIsNotValidException {
-        log.info("Executing operation sendMessage");
-        if (messageMetaData == null) {
-			log.error("Die erforderliche Header Variable 'messageMetaData' wurde nicht gefunden");
-            return;
-        }
-        validateMessageId(messageMetaData);
-        validator.checkMessage(genericContainer);
+	private final RequestMapper requestMapper;
+	private final ExceptionMapper exceptionMapper;
+	private final XtaMessageService xtaMessageService;
 
-        xtaMessageService.sendMessage(requestMapper.mapXtaMessageFromGenericContentContainer(genericContainer, messageMetaData));
-    }
+	/*
+	 * (non-Javadoc)
+	 * @see genv3.de.xoev.transport.xta.x211.SendPortType#sendMessage(genv3.de.xoev.transport.xta.x211.
+	 * GenericContentContainer genericContainer, genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData messageMetaData,
+	 * genv3.eu.osci.ws.x2008.x05.transport.X509TokenContainerType x509TokenContainer)*
+	 */
+	@Override
+	public void sendMessage(final GenericContentContainer genericContainer,
+			final genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData messageMetaData,
+			final genv3.eu.osci.ws.x2008.x05.transport.X509TokenContainerType x509TokenContainer)
+			throws SyncAsyncException, XTAWSTechnicalProblemException, MessageVirusDetectionException,
+			MessageSchemaViolationException, PermissionDeniedException, ParameterIsNotValidException {
+		log.info("Executing operation sendMessage");
+		var request = requestMapper.mapXtaMessageFromGenericContentContainer(genericContainer, messageMetaData);
+		validator.validate(request);
 
-    public void validateMessageId(MessageMetaData messageMetaData) throws ParameterIsNotValidException {
-        if (messageMetaData.getMsgIdentification() == null || messageMetaData.getMsgIdentification().getMessageID() == null) {
-            throw new ParameterIsNotValidException("Message ID is missing");
-        }
-    }
+		if (!xtaMessageService.sendMessage(request)) {
+			throw exceptionMapper.createParameterIsNotValidException("Failed to send message");
+		}
+	}
 
-    /*
-     * (non-Javadoc)
-     * @see genv3.de.xoev.transport.xta.x211.SendPortType#sendMessageSync(genv3.de.xoev.transport.xta.x211.
-     * GenericContentContainer genericContainer, genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData messageMetaData,
-     * genv3.eu.osci.ws.x2008.x05.transport.X509TokenContainerType x509TokenContainer)*
-     */
-    @Override
-    public void sendMessageSync(final jakarta.xml.ws.Holder<GenericContentContainer> genericContainer,
-            final jakarta.xml.ws.Holder<genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData> messageMetaData,
-            final jakarta.xml.ws.Holder<genv3.eu.osci.ws.x2008.x05.transport.X509TokenContainerType> x509TokenContainer)
-            throws SyncAsyncException, XTAWSTechnicalProblemException, MessageVirusDetectionException,
-            MessageSchemaViolationException, PermissionDeniedException, ParameterIsNotValidException {
-        log.info("Executing operation sendMessageSync");
-        throw new UnsupportedOperationException("sendMessageSync is not supported");
-    }
+	/*
+	 * (non-Javadoc)
+	 * @see genv3.de.xoev.transport.xta.x211.SendPortType#sendMessageSync(genv3.de.xoev.transport.xta.x211.
+	 * GenericContentContainer genericContainer, genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData messageMetaData,
+	 * genv3.eu.osci.ws.x2008.x05.transport.X509TokenContainerType x509TokenContainer)*
+	 */
+	@Override
+	public void sendMessageSync(final jakarta.xml.ws.Holder<GenericContentContainer> genericContainer,
+			final jakarta.xml.ws.Holder<genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData> messageMetaData,
+			final jakarta.xml.ws.Holder<genv3.eu.osci.ws.x2008.x05.transport.X509TokenContainerType> x509TokenContainer)
+			throws SyncAsyncException, XTAWSTechnicalProblemException, MessageVirusDetectionException,
+			MessageSchemaViolationException, PermissionDeniedException, ParameterIsNotValidException {
+		log.info("Executing operation sendMessageSync");
+		throw new UnsupportedOperationException("sendMessageSync is not supported");
+	}
 
 }
diff --git a/src/main/java/de/ozgcloud/xta/test/app/service/ParameterValidatorService.java b/src/main/java/de/ozgcloud/xta/test/app/service/ParameterValidatorService.java
deleted file mode 100644
index f885d59a2e59ff9858587c8e75549366e2abbded..0000000000000000000000000000000000000000
--- a/src/main/java/de/ozgcloud/xta/test/app/service/ParameterValidatorService.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * @formatter:off
- *
- * Copyright 2021-2022  Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the European Public License, Version 1.2 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     https://opensource.org/licenses/EUPL-1.2
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * @formatter:on
- */
-package de.ozgcloud.xta.test.app.service;
-
-import java.util.List;
-import java.util.Optional;
-
-import org.springframework.stereotype.Service;
-
-import genv3.de.xoev.transport.xta.x211.ContentType;
-import genv3.de.xoev.transport.xta.x211.GenericContentContainer;
-import genv3.de.xoev.transport.xta.x211.GenericContentContainer.ContentContainer;
-import genv3.eu.osci.ws.x2008.x05.transport.MsgSelector;
-import genv3.eu.osci.ws.x2014.x10.transport.DestinationsType;
-import genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData;
-import genv3.eu.osci.ws.x2014.x10.transport.MsgIdentificationType;
-import genv3.eu.osci.ws.x2014.x10.transport.OriginatorsType;
-import genv3.eu.osci.ws.x2014.x10.transport.PartyIdentifierType;
-import genv3.eu.osci.ws.x2014.x10.transport.PartyType;
-import genv3.eu.osci.ws.x2014.x10.transport.QualifierType;
-import lombok.extern.log4j.Log4j2;
-
-@Log4j2
-@Service
-public class ParameterValidatorService {
-
-	public boolean isNotNull(final Object obj, final CharSequence parameter) {
-		if (obj == null) {
-			log.error("Parameter '{}' was null", parameter);
-			return false;
-		}
-		return true;
-	}
-
-	public boolean isNotBlank(final String str, final CharSequence parameter) {
-		boolean result = isNotNull(str, parameter);
-		if (result && str.trim().length() == 0) {
-			log.error("Parameter '{}' was blank", parameter);
-			return false;
-		}
-		return result;
-	}
-
-	public boolean isEquals(final String expectedStr, final String otherStr, final CharSequence parameter) {
-		if (isNotNull(otherStr, parameter)) {
-			if (!expectedStr.equals(otherStr)) {
-				log.error("Parameter '{}' was wrong. expected='{}' received='{}'", parameter, expectedStr, otherStr);
-			}
-			return false;
-		}
-		return true;
-	}
-
-	public boolean isListNotEmpty(final List<?> list, final CharSequence parameter) {
-		boolean result = isNotNull(list, parameter);
-		if (result && list.isEmpty()) {
-			log.error("Parameter list '{}' was empty", parameter);
-			return false;
-		}
-		return result;
-	}
-
-	public boolean isListSizeEquals(final List<?> list, final int expectedSize, final CharSequence parameter) {
-		boolean result = isNotNull(list, parameter);
-		if (result && list.size() != expectedSize) {
-			log.error("Parameter list '{}' has wrong size.", parameter);
-			return false;
-		}
-		return result;
-	}
-
-	public void checkMessageMetaData(final MessageMetaData messageMetaData, // NOSONAR
-			final Optional<String> expectedMessageId) {
-		XtaParameter param = XtaParameter.MESSAGE_META_DATA;
-		// TODO scenario is needed to check delivery attributes
-		if (isNotNull(messageMetaData, param)) {
-			// TODO use ScenarioRole to check the properties see Table 5.1 of the specification
-			// if (isNotNull(messageMetaData.getDeliveryAttributes(), param.join(XtaParameter.DELIVERY_ATTRIBUTES))) {
-			// XtaParameter subparam = param.join(XtaParameter.DELIVERY_ATTRIBUTES);
-			// DeliveryAttributesType deliveryAttributes = messageMetaData.getDeliveryAttributes();
-			// isNotNull(deliveryAttributes.getDelivery(), subparam.join(XtaParameter.DELIVERY));
-			// isNotNull(deliveryAttributes.getInitialFetch(), subparam.join(XtaParameter.INITIAL_FETCH));
-			// isNotNull(deliveryAttributes.getInitialSend(), subparam.join(XtaParameter.INITIAL_SEND));
-			// isNotNull(deliveryAttributes.getOrigin(), subparam.join(XtaParameter.ORIGIN));
-			// }
-			if (isNotNull(messageMetaData.getOriginators(), param.join(XtaParameter.ORIGINATORS))) {
-				XtaParameter subparam = param.join(XtaParameter.ORIGINATORS);
-				OriginatorsType originators = messageMetaData.getOriginators();
-				checkPartyType(originators.getAuthor(), subparam.join(XtaParameter.AUTHOR));
-				if (originators.getSender() != null) {
-					checkPartyType(originators.getSender(), subparam.join(XtaParameter.SENDER));
-				} else {
-					// TODO wir haben keine protokoll-warnung, daher nur eine log-message
-					log.warn("originator/sender is missing, but it's not required");
-				}
-			}
-			if (isNotNull(messageMetaData.getDestinations(), param.join(XtaParameter.DESTINATIONS))) {
-				DestinationsType destinations = messageMetaData.getDestinations();
-				checkPartyType(destinations.getReader(), param.join(XtaParameter.DESTINATIONS, XtaParameter.READER));
-			}
-			if (isNotNull(messageMetaData.getMsgIdentification(), param.join(XtaParameter.MSG_IDENTIFICATION))) {
-				MsgIdentificationType msgIdentification = messageMetaData.getMsgIdentification();
-				if (expectedMessageId.isPresent()) {
-					isEquals(expectedMessageId.get(), msgIdentification.getMessageID().getValue(),
-							param.join(XtaParameter.MSG_IDENTIFICATION, XtaParameter.MESSAGE_ID));
-				}
-			}
-			if (isNotNull(messageMetaData.getQualifier(), param.join(XtaParameter.QUALIFIER))) {
-				XtaParameter subparam = param.join(XtaParameter.QUALIFIER);
-				QualifierType qualifier = messageMetaData.getQualifier();
-				isNotNull(qualifier.getService(), subparam.join(XtaParameter.SERVICE));
-				isNotNull(qualifier.getBusinessScenario(), param.join(XtaParameter.BUSINESS_SCENARIO));
-				isNotNull(qualifier.getMessageType(), param.join(XtaParameter.MESSAGE_TYPE));
-			}
-			isNotNull(messageMetaData.getMsgSize(), param.join(XtaParameter.MSG_SIZE));
-		}
-	}
-
-	public void checkPartyType(final PartyType partyType, final XtaParameter parameter) {
-		if (isNotNull(partyType, parameter)) {
-			XtaParameter subparam = parameter.join(XtaParameter.IDENTIFIER);
-			if (isNotNull(partyType.getIdentifier(), subparam)) {
-				PartyIdentifierType identifier = partyType.getIdentifier();
-				isNotBlank(identifier.getCategory(), subparam.join(XtaParameter.CATEGORY));
-				isNotBlank(identifier.getType(), subparam.join(XtaParameter.TYPE));
-			}
-		}
-	}
-
-	public void checkMessage(final GenericContentContainer request) {
-		if (request.getContentContainer() == null && request.getEncryptedData() == null) {
-			log.error("No ContentContainer or EncryptedData element found");
-		} else if (request.getContentContainer() != null) {
-			ContentContainer contentContainer = request.getContentContainer();
-			if (isNotNull(contentContainer.getMessage(), XtaParameter.MESSAGE)) {
-				ContentType message = contentContainer.getMessage();
-				isNotNull(message.getValue(), XtaParameter.MESSAGE.join("value"));
-				isNotBlank(message.getContentType(), XtaParameter.MESSAGE.join("contentType"));
-				isNotBlank(message.getEncoding(), XtaParameter.MESSAGE.join("encoding"));
-				isNotBlank(message.getFilename(), XtaParameter.MESSAGE.join("filename"));
-				isNotBlank(message.getId(), XtaParameter.MESSAGE.join("id"));
-				isNotNull(message.getSize(), XtaParameter.MESSAGE.join("size"));
-			}
-		} else {
-			log.info("message is encryptd");
-		}
-	}
-
-	public void checkMsgSelector(final MsgSelector msgSelector, final Optional<String> expectedMessageId) {
-		if (isNotNull(msgSelector, XtaParameter.MSG_SELECTOR)) {
-			isNotNull(msgSelector.isNewEntry(), XtaParameter.MSG_SELECTOR.join("newEntry"));
-			isNotNull(msgSelector.getMsgBoxEntryTimeFrom(),
-					XtaParameter.MSG_SELECTOR.join("MsgBoxEntryTimeFrom"));
-			isNotNull(msgSelector.getMsgBoxEntryTimeTo(),
-					XtaParameter.MSG_SELECTOR.join("MsgBoxEntryTimeTo"));
-			if (expectedMessageId.isPresent() && isListNotEmpty(msgSelector.getMessageID(),
-					XtaParameter.MSG_SELECTOR.join(XtaParameter.MESSAGE_ID))) {
-				isEquals(expectedMessageId.get(), msgSelector.getMessageID().get(0).getValue(),
-						XtaParameter.MSG_SELECTOR.join(XtaParameter.MESSAGE_ID));
-			}
-		}
-	}
-}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/service/XtaMessageService.java b/src/main/java/de/ozgcloud/xta/test/app/service/XtaMessageService.java
index 3c9dcdb6ce7b7d472881f91fe09cc54e0c800261..79864e4fce2136fb06d23e29f0a2796991b32553 100644
--- a/src/main/java/de/ozgcloud/xta/test/app/service/XtaMessageService.java
+++ b/src/main/java/de/ozgcloud/xta/test/app/service/XtaMessageService.java
@@ -2,10 +2,15 @@ package de.ozgcloud.xta.test.app.service;
 
 import java.util.List;
 import java.util.Optional;
+import java.util.UUID;
+import java.util.function.Predicate;
 
+import org.springframework.core.env.Environment;
 import org.springframework.stereotype.Service;
 
 import de.ozgcloud.xta.test.app.data.XtaMessageRepository;
+import de.ozgcloud.xta.test.app.model.XtaCloseRequest;
+import de.ozgcloud.xta.test.app.model.XtaGetMessageRequest;
 import de.ozgcloud.xta.test.app.model.XtaMessage;
 import de.ozgcloud.xta.test.app.model.XtaMessageMetaData;
 import de.ozgcloud.xta.test.app.model.XtaMessageMetaDataListing;
@@ -17,15 +22,18 @@ import lombok.RequiredArgsConstructor;
 public class XtaMessageService {
 	private final XtaMessageRepository messageRepository;
 
-	public void sendMessage(XtaMessage message) {
+	private final Environment environment;
+
+	public boolean sendMessage(XtaMessage message) {
 		messageRepository.save(message);
+		return true;
 	}
 
 	public XtaMessageMetaDataListing getStatusList(XtaMessageMetaDataListingRequest listingRequest) {
 		return XtaMessageMetaDataListing.builder()
-				.pendingMessageCount(messageRepository.countByReaderIdentifierValue(listingRequest.clientIdentifierValue()))
+				.pendingMessageCount(messageRepository.countByReaderIdentifierValue(listingRequest.clientIdentifier().value()))
 				.messages(getMetaData(messageRepository.findByReaderIdentifierValueLimitedTo(
-						listingRequest.clientIdentifierValue(),
+						listingRequest.clientIdentifier().value(),
 						listingRequest.maxListItems())))
 				.build();
 	}
@@ -36,11 +44,37 @@ public class XtaMessageService {
 				.toList();
 	}
 
-	public Optional<XtaMessage> getMessage(String identifierValue) {
-		return messageRepository.get(identifierValue);
+	public Optional<XtaMessage> getMessage(XtaGetMessageRequest request) {
+		return messageRepository.get(request.messageId())
+				.filter(isAuthorOrReaderOfMessage(request.clientIdentifier().value()));
+	}
+
+	Predicate<XtaMessage> isAuthorOrReaderOfMessage(String clientIdentifierValue) {
+		return m -> m.metaData().readerIdentifier().value().equals(clientIdentifierValue)
+				|| m.metaData().authorIdentifier().value().equals(clientIdentifierValue);
+	}
+
+	public boolean closeMessage(XtaCloseRequest request) {
+		return messageRepository.deleteByMessageIdAndReaderIdentifierValue(
+				request.messageId(),
+				request.clientIdentifier().value()
+		);
+	}
+
+	public String createMessageId() {
+		return generateXtaIdWithNamespace("de:xta:messageid");
+	}
+
+	public String createRequestId() {
+		return generateXtaIdWithNamespace("de:xta:requestid");
 	}
 
-	public void closeMessage(String identifierValue) {
-		messageRepository.delete(identifierValue);
+	private String generateXtaIdWithNamespace(String namespace) {
+		return String.join(":",
+				"urn",
+				namespace,
+				environment.getProperty("spring.application.name"),
+				UUID.randomUUID().toString()
+		);
 	}
 }
diff --git a/src/main/java/de/ozgcloud/xta/test/app/service/XtaParameter.java b/src/main/java/de/ozgcloud/xta/test/app/service/XtaParameter.java
deleted file mode 100644
index 1a645dd76817e65d9bf874f9dbf873218b38bcee..0000000000000000000000000000000000000000
--- a/src/main/java/de/ozgcloud/xta/test/app/service/XtaParameter.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * @formatter:off
- *
- * Copyright 2021-2022  Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the European Public License, Version 1.2 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     https://opensource.org/licenses/EUPL-1.2
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * @formatter:on
- */
-package de.ozgcloud.xta.test.app.service;
-
-import java.util.StringJoiner;
-
-import groovy.transform.EqualsAndHashCode;
-
-@EqualsAndHashCode
-public class XtaParameter implements CharSequence {
-
-	private static final String SEPARATOR = ".";
-
-	public static final XtaParameter AUTHOR = new XtaParameter("Author");
-	public static final XtaParameter BUSINESS_SCENARIO = new XtaParameter("BusinessScenario");
-	public static final XtaParameter CATEGORY = new XtaParameter("category");
-	public static final XtaParameter DELIVERY = new XtaParameter("Delivery");
-	public static final XtaParameter DELIVERY_ATTRIBUTES = new XtaParameter("DeliveryAttributes");
-	public static final XtaParameter DESTINATIONS = new XtaParameter("Destinations");
-	public static final XtaParameter IDENTIFIER = new XtaParameter("Identifier");
-	public static final XtaParameter INITIAL_FETCH = new XtaParameter("InitialFetch");
-	public static final XtaParameter INITIAL_SEND = new XtaParameter("InitialSend");
-	public static final XtaParameter MESSAGE = new XtaParameter("Message");
-	public static final XtaParameter MESSAGE_ID = new XtaParameter("MessageID");
-	public static final XtaParameter MESSAGE_META_DATA = new XtaParameter("MessageMetaData");
-	public static final XtaParameter MESSAGE_TYPE = new XtaParameter("MessageType");
-	public static final XtaParameter MSG_BOX_REQUEST_ID = new XtaParameter("MsgBoxRequestID");
-	public static final XtaParameter MSG_BOX_RESPONSE = new XtaParameter("MsgBoxResponse");
-	public static final XtaParameter MSG_IDENTIFICATION = new XtaParameter("MsgIdentification");
-	public static final XtaParameter MSG_SELECTOR = new XtaParameter("MsgSelector");
-	public static final XtaParameter MSG_SIZE = new XtaParameter("MsgSize");
-	public static final XtaParameter QUALIFIER = new XtaParameter("Qualifier");
-	public static final XtaParameter READER = new XtaParameter("Reader");
-	public static final XtaParameter SENDER = new XtaParameter("Sender");
-	public static final XtaParameter SERVICE = new XtaParameter("Service");
-	public static final XtaParameter ORIGIN = new XtaParameter("Origin");
-	public static final XtaParameter ORIGINATORS = new XtaParameter("Originators");
-	public static final XtaParameter TYPE = new XtaParameter("type");
-
-	private String parameter;
-
-	public XtaParameter(final String parameter) {
-		this.parameter = parameter;
-	}
-
-	public XtaParameter join(final CharSequence parameter) {
-		return new XtaParameter(this.parameter + SEPARATOR + parameter);
-	}
-
-	public XtaParameter join(final CharSequence parameter, final CharSequence parameter2) {
-		return new XtaParameter(this.parameter + SEPARATOR + parameter + SEPARATOR + parameter2);
-	}
-
-	public XtaParameter join(final CharSequence parameter, final CharSequence... charSequences) {
-		StringJoiner stringJoiner = new StringJoiner(SEPARATOR);
-		stringJoiner.add(this.parameter);
-		stringJoiner.add(parameter);
-		for (int i = 0; i < charSequences.length; i++) {
-			stringJoiner.add(charSequences[i]);
-		}
-		return new XtaParameter(stringJoiner.toString());
-	}
-
-	@Override
-	public int length() {
-		return parameter.length();
-	}
-
-	@Override
-	public char charAt(final int index) {
-		return parameter.charAt(index);
-	}
-
-	@Override
-	public CharSequence subSequence(final int start, final int end) {
-		return parameter.subSequence(start, end);
-	}
-
-	@Override
-	public String toString() {
-		return parameter;
-	}
-}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/util/XtaId.java b/src/main/java/de/ozgcloud/xta/test/app/util/XtaId.java
deleted file mode 100644
index 7ab923459f48656619562b5f29ba93920e96ec68..0000000000000000000000000000000000000000
--- a/src/main/java/de/ozgcloud/xta/test/app/util/XtaId.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * @formatter:off
- *
- * Copyright 2021-2022  Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the European Public License, Version 1.2 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     https://opensource.org/licenses/EUPL-1.2
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * @formatter:on
- */
-package de.ozgcloud.xta.test.app.util;
-
-import java.util.Optional;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import lombok.Data;
-
-@Data
-public class XtaId {
-
-	public static final Pattern PATTERN = Pattern.compile("(\\w+):(.+):([^:]+):([^:]+)");
-	private final String schema;
-	private final String namespace;
-	private final String application; // prefix
-	private final String uuid; // identifier
-
-	public XtaId(final String schema, final String namespace, final String application, final String uuid) {
-		this.schema = schema;
-		this.namespace = namespace;
-		this.application = application;
-		this.uuid = uuid;
-	}
-
-	@Override
-	public String toString() {
-		return schema + ":" + namespace + ":" + application + ":" + uuid;
-	}
-
-	public static Optional<XtaId> parse(final String messageId) {
-		// page 119; structure: "urn:de:xta:messageid:<Präfix>:<Identifikator>"
-		Matcher matcher = PATTERN.matcher(messageId);
-		if (matcher.matches()) {
-			return Optional
-					.of(new XtaId(matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(4)));
-		}
-		return Optional.empty();
-	}
-}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/util/XtaIdGenerator.java b/src/main/java/de/ozgcloud/xta/test/app/util/XtaIdGenerator.java
deleted file mode 100644
index dee237791545aa4048b75259358ec00fceedd665..0000000000000000000000000000000000000000
--- a/src/main/java/de/ozgcloud/xta/test/app/util/XtaIdGenerator.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * @formatter:off
- *
- * Copyright 2021-2022  Koordinierungsstelle für IT-Standards (KoSIT)
- *
- * Licensed under the European Public License, Version 1.2 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     https://opensource.org/licenses/EUPL-1.2
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * @formatter:on
- */
-package de.ozgcloud.xta.test.app.util;
-
-import java.util.UUID;
-
-import lombok.experimental.UtilityClass;
-
-@UtilityClass
-public class XtaIdGenerator {
-
-	public static final String MESSAGE_ID_NAMESPACE = "de:xta:messageid";
-	public static final String REQUEST_ID_NAMESPACE = "de:xta:requestid";
-
-	public static final String APPLICATION_NAME = "xta-test-server";
-
-	public static XtaId generateMessageId() {
-		return generateId(MESSAGE_ID_NAMESPACE);
-	}
-
-	public static XtaId generateRequestId() {
-		return generateId(REQUEST_ID_NAMESPACE);
-	}
-
-	public static XtaId generateId(final String namespace) {
-		return new XtaId("urn", namespace, APPLICATION_NAME, UUID.randomUUID().toString());
-	}
-}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/util/YamlPropertySourceFactory.java b/src/main/java/de/ozgcloud/xta/test/app/util/YamlPropertySourceFactory.java
deleted file mode 100644
index 3828423a6f600f2189ff0baaeb0843491ab8d352..0000000000000000000000000000000000000000
--- a/src/main/java/de/ozgcloud/xta/test/app/util/YamlPropertySourceFactory.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Created 2023-03-24
- */
-package de.ozgcloud.xta.test.app.util;
-
-import java.io.IOException;
-import java.util.Properties;
-
-import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
-import org.springframework.core.env.PropertiesPropertySource;
-import org.springframework.core.env.PropertySource;
-import org.springframework.core.io.support.EncodedResource;
-import org.springframework.core.io.support.PropertySourceFactory;
-
-public class YamlPropertySourceFactory implements PropertySourceFactory {
-
-	@Override
-	public PropertySource<?> createPropertySource(final String name, final EncodedResource encodedResource)
-			throws IOException {
-		if (encodedResource == null) {
-			throw new IOException("Resource is null");
-		}
-		YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
-		if (!encodedResource.getResource().exists()) {
-			return new PropertiesPropertySource(name, null);
-		}
-		factory.setResources(encodedResource.getResource());
-
-		Properties properties = factory.getObject();
-
-		return new PropertiesPropertySource(name, properties);
-	}
-}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/validation/RequestValidator.java b/src/main/java/de/ozgcloud/xta/test/app/validation/RequestValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..3474a645860d9291ca824c4760b124b9e8900e33
--- /dev/null
+++ b/src/main/java/de/ozgcloud/xta/test/app/validation/RequestValidator.java
@@ -0,0 +1,53 @@
+package de.ozgcloud.xta.test.app.validation;
+
+import java.util.Collection;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import jakarta.annotation.Nullable;
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.Validation;
+import jakarta.validation.Validator;
+
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.xta.test.app.mapper.ExceptionMapper;
+import genv3.de.xoev.transport.xta.x211.XTAWSTechnicalProblemException;
+import lombok.RequiredArgsConstructor;
+
+@Service
+@RequiredArgsConstructor
+public class RequestValidator {
+
+	private static final Validator VALIDATOR;
+
+	static {
+		try (var factory = Validation.buildDefaultValidatorFactory()) {
+			VALIDATOR = factory.getValidator();
+		}
+	}
+
+	private final ExceptionMapper exceptionMapper;
+
+	public <T> void validate(@Nullable T request) throws XTAWSTechnicalProblemException {
+		if (request == null) {
+			throw exceptionMapper.createTechnicalProblemException("Request is invalid: null");
+		}
+		validate(request, violations ->
+				exceptionMapper.createTechnicalProblemException("Request is invalid:\n" + getViolationsDescription(violations))
+		);
+	}
+
+	private <T> String getViolationsDescription(Collection<ConstraintViolation<T>> violations) {
+		return violations.stream()
+				.map(v -> "'%s' %s".formatted(v.getPropertyPath().toString(), v.getMessage()))
+				.collect(Collectors.joining("\n"));
+	}
+
+	private <T, E extends Exception> void validate(T request, Function<Collection<ConstraintViolation<T>>, E> violationsConsumer) throws E {
+		var violations = VALIDATOR.validate(request);
+		if (!violations.isEmpty()) {
+			throw violationsConsumer.apply(violations);
+		}
+	}
+}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/validation/ValidXtaId.java b/src/main/java/de/ozgcloud/xta/test/app/validation/ValidXtaId.java
new file mode 100644
index 0000000000000000000000000000000000000000..94bdd31cc9ab0786a25c13b8d97b2930cc14250a
--- /dev/null
+++ b/src/main/java/de/ozgcloud/xta/test/app/validation/ValidXtaId.java
@@ -0,0 +1,28 @@
+package de.ozgcloud.xta.test.app.validation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+
+@Constraint(validatedBy = XtaIdValidator.class)
+@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.PARAMETER })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ValidXtaId {
+	String MESSAGE_ID_NAMESPACE = "de:xta:messageid";
+	String REQUEST_ID_NAMESPACE = "de:xta:requestid";
+	String ANY_NAMESPACE = ".+";
+
+	String message() default "Invalid xta id";
+
+	String namespace() default ANY_NAMESPACE;
+
+	Class<?>[] groups() default {};
+
+	Class<? extends Payload>[] payload() default {};
+}
+
+
diff --git a/src/main/java/de/ozgcloud/xta/test/app/validation/XtaIdValidator.java b/src/main/java/de/ozgcloud/xta/test/app/validation/XtaIdValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..e5187cdbc98c355cdbc7fbde5a918598bd04e773
--- /dev/null
+++ b/src/main/java/de/ozgcloud/xta/test/app/validation/XtaIdValidator.java
@@ -0,0 +1,23 @@
+package de.ozgcloud.xta.test.app.validation;
+
+import java.util.regex.Pattern;
+
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+
+public class XtaIdValidator implements ConstraintValidator<ValidXtaId, String> {
+
+	private Pattern pattern;
+
+	@Override
+	public void initialize(ValidXtaId constraintAnnotation) {
+		pattern = Pattern.compile(
+				"(\\w+):(" + constraintAnnotation.namespace() + "):([^:]+):([^:]+)"
+		);
+	}
+
+	@Override
+	public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
+		return value != null && pattern.matcher(value).matches();
+	}
+}
diff --git a/src/main/resources/application_second_app.yml b/src/main/resources/application_second_app.yml
deleted file mode 100644
index d86b9160a716df6c3cacd046088fd1384065defe..0000000000000000000000000000000000000000
--- a/src/main/resources/application_second_app.yml
+++ /dev/null
@@ -1,48 +0,0 @@
-spring:
-  application: 
-    name: xta-test-server
-  servlet:
-    multipart:
-      max-file-size: 10MB
-      max-request-size: 10MB
-  devtools:
-    livereload:
-      port: 35730
-
-server:
-  port: 9443
-  tomcat.max-http-post-size: 10MB
-  tomcat.max-swallow-size: 10MB
-  ssl:
-    # enthaelt den privaten und oeffentlichen Schluessel der Anwendung
-    key-store: classpath:store/xta-test-server_keystore.p12
-    key-store-password: password
-    key-store-type: pkcs12
-    # Alias im KeyStore
-    key-alias: xta-test-application
-    key-password: password
-    # enthaelt alle vertrauenswuerdigen Zertifikate
-    trust-store: classpath:store/xta-test-server_truststore.jks
-    trust-store-password: password
-    trust-store-type: JKS
-    # want, need, none; see org.springframework.boot.web.server.ClientAuth
-    # wird ein Client Zertifikat benoetigt
-    client-auth: want
-  thymeleaf.cache: false
-
-app:
-  server:
-    http-port: 9080
-    redirect-to-https: false
-
-logging:
-  level:
-    ROOT: INFO
-    # no auto configuration report
-    org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener: INFO
-    org.springframework.security: WARN
-    org.springframework.web: INFO
-    org.apache.axiom: INFO
-    de.ozgcloud.xta.test.app.soap: DEBUG
-    org.apache.axis2: INFO
-    
diff --git a/src/main/resources/defaultEncodedFile.txt b/src/main/resources/defaultEncodedFile.txt
deleted file mode 100644
index 8bedbda4ed1c6c3801ede26bbf0ec13eabb4f59d..0000000000000000000000000000000000000000
--- a/src/main/resources/defaultEncodedFile.txt
+++ /dev/null
@@ -1,86 +0,0 @@
-<xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
-                    Type="http://www.w3.org/2001/04/xmlenc#Element">
-    <xenc:EncryptionMethod Algorithm="http://www.w3.org/2009/xmlenc11#aes256-gcm"/>
-    <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
-        <xenc:EncryptedKey>
-            <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#kw-aes256"/>
-            <xenc:CipherData>
-                <xenc:CipherValue>VGqYuIiGc46HchelmoqJDu5Rot/owBiNer3IaUNU2XTGZs2o6VsyJQ==</xenc:CipherValue>
-            </xenc:CipherData>
-        </xenc:EncryptedKey>
-    </ds:KeyInfo>
-    <xenc:CipherData>
-        <xenc:CipherValue>DN20Xw+J0riHWj308znVIDlLoMh0QP6xJz7tbYDaUqOhqITD+PwJHvQ576k3QFOGwSc0ihiszITA&#13;
-5Q0heheYz5QZwNCH7frTcl6OYFqKG1fvei8xlfdWHsJ/cGz7A4H90UrR/Bm1jDrP+HYfi4KbnRbm&#13;
-fHRdd7k/zySuQ28FSCTiZKg1YMoPmx/KF3Sc1jkmKj+OFPvbzeaHEI+l6tr+oWHB7PGAJVdIE5w/&#13;
-/uwdIwIm/AELtGdb3JAOqHlHwAQBo6TL9q8FGzKrnJMJwR4K8J/9yPnor5DotWLPJ5ZdcPFRSfle&#13;
-6cNBR9Y4q3ZE/OKDz81lmNYIabJ8bVK45+dvo8ME8UqhZPNwDUy7XmPZa5Qnob6pvrmDpYp7g14c&#13;
-VoHK8E1Pl8DBdD7gY86pGsNC0ApXhCwZxlLYP+7Wizpot0mnRorcETmfdKk2YqfE0URk2Aob/L4y&#13;
-z0/bSqtleh0ybe6kxGdhFBlEzcwyfh325NQyUkLqvxlgjk4SzIbbNkyXofSfzE3XWqMLOYUGT6lN&#13;
-25HYyOogM6OCfjL0d9UH79Fe5Q3zdUyhZoDPkNhhBYFhj6ol20eU5MlHjOEnSOeN3qGaGrx2eIcZ&#13;
-s6gw8+R0Jo9fd4litsB1zTER4Cv9FxDy1HCODuWCrQOB6Wtuk+BJmeOksElnY7I9DQRWfT/vnrDM&#13;
-zob/AxYhgyiV1Qp8E8VKPug69yWolZLNZdZpTLTo5RZtGnaTZ9w9tzA/DWxH9J8p6LKsek10njgg&#13;
-UP+cFwoUus1j040h89UOYbhoXqwK7ob7LBLlT0JVWeuSwzni+N/Z6R/Wb4z1fc1L6vphPVVjcwr9&#13;
-3rkB9UDRu7qhoWdzhGXf3Zky5LpBPon8jB5y1RRP/dZk+aBu6MaDNR5ulEFhK61nb5K+u5YBj43H&#13;
-hVj84sLKVI7QlY2lRtNdtM55JTqEv1BUHmldPfc6IYj9rDI0HCKheovuvdvxjY8FU8VT+4WjAX1C&#13;
-7lW9+itQerGFhj/HTEEc4U2kepw0jPPUGTqhCALtybhK6lsakV2cEL3z/u5CtysrUGIz/QZ0UAHT&#13;
-ydId56UOaWeqWI9zT55qdqdJ2qnlmo0T/1X8R8Awr3VusujtzyBIhDYkZFOp53vzx4Zm8VTMO3Q2&#13;
-rFZ0aHJ/qVd2xkqHTNVcyqHhgTGlzpizkq3um9rA/KDjxLMWn39R5Kwl79suvO0SRcuNT9X1Cacn&#13;
-obBRXhXV3BCI5vn1kLtgLk+uwkODGGN6/+/6v4wbcswNebzOs0dtSsDdyaZOJSFF2/hBtGKjs4Mj&#13;
-52NVSTWTsG8T9gCtrnkqGbVsx33HgogqlK1N4i4uEh8go1u7CteACNqsT0bntrAqQ0sDL1irAfX4&#13;
-p8Q9+wUEGNGZysNWPoqpdbIsZy/klWz1RW5UVczF9hReYuI7s6AIJCs8ZWmLM8zET33EvkbRs5kL&#13;
-jQij5hYhCU+Gx3JnpcZ7/Zg68GqWMxQAI84IU38/gkLgfiCe4CXjEGgtLHrk43OXdFe1Nt84Z7Wp&#13;
-ov3xIZyC4wvXEkcqmkvMYX8sjwl+wf8gSwgi/+TSzOVmkgBJedyEvVDMkaCyQjcGVWu6W0uHggNG&#13;
-de6UBixycYnq0kjPt5eQVtJWdkOoSxfsrYudzSAQvl8rLtAVaSOuRE3jT8jzbQp8lu4JQBnzQiFv&#13;
-HG9rhVlmCUGdVeQDd2JQYBNDy5C/mGW04TCYbHYNHoPaHZE4kBlJHWTjz+RDHjEBmMQ4g8jkJDgb&#13;
-K9cWi3vxyBjambbxjHPLIdWnMrptiSHoVggKNXeWlwcAZ5gcPIcr61dJOjXHUpAnLyaQDjEibdmz&#13;
-rcLA3rujRGqu44rtGG0E8xgRbcqsiIUOTvlIYluqerxz1GyyjCA6gc6SoSitPv3Eyv0aMawEdXAU&#13;
-8J1eITekQ9MMIC/VUxWaTRLlWB1bbXeRzDrJ+/Hh/KWLuc5RerTq56stz/cb1+u+qZ/xWNXWbFz7&#13;
-3ik9XJYg4UHJ/pBGdCzdD+U6E1s2oIRM0dJy2+PS7jYUfKItaI/asoYuS1S4THH3A9e8MbDkAkPl&#13;
-CozPHEIGGZ3GhwZQCcFxK5ZtYdWt3AdBFt+RI5fU07JlIbADs+1HnZ+QfATb2OUBuOjM1MW1nLkg&#13;
-iOZW+IMDxS0hS0+QpUzFw2n848N4SLJegIGDKW/GJ5oVkC4giUsDirQNytIPImjDlSzQgVwCOAwj&#13;
-g/wnX3qtLUWWysICAuSAkGGmfsrLtlANdSEtdhLOdPy31QM4X+u7jGDogUpZFc4aIFeLg5yGv75F&#13;
-y/rZ9JfgzY1fNnkLfCHEXb0txtOC88/LsYzr2JgBnv1PiIKVPDHrKWxCfsfMCyFOABvohsxTQ//A&#13;
-YwZhnY69lPe/S+a/+GrE1gZfh2dDtJ6zsq6tcdZD3a/3QSA2/y+1CflIwGf5o5tYLYg9ou8yET/4&#13;
-G8bozFFuii6IBGVJTn+k3NnwiIvet1TwsMUAWVh7SpI0HQp2/7Gz/UkjewPRy9ZxgWwWqnbLL2au&#13;
-OqKfRnlKCmNn2FzASl53f0wOG1f9seE73jQhORRh+HCdmhJDFgh5aeH092GKFyklwycByMwgMcmR&#13;
-H8oRMY4UY0UGcaSGOqlYd2NJl6H0J0BxI6PFHN5a4bu+KpLvaRrErTvpox5Kt3wDpicYTLlQyVnz&#13;
-8yql85jidzNw/0pkpxnRkjcxJlC0cMKochLgi66SbSa9+Z12710h0/kVGhgtV1+/Ee6C47tuNDY1&#13;
-Qx301lpCJg9+/tWvuuUQqKbTwjk4dF6aBu3SNTCOXuMaJoxN6hrjoZD+YlwTkxx32bwxvbCx8ztk&#13;
-O7E1uayZ9rcLaDra1SzmRwkqaEtkPD9+JaWF8Vdh11lG2u1I/CXhZxQ6Mu6WhWg/rNDqynQ04TOu&#13;
-vAN9+0RH6Aln6yVSun2TJPs7BqpSKUP9NGXUHdOtkExKKd52RCtHZX59uqGjAhBdu4zlUKCK8aup&#13;
-7lyBkRJgvSCIoJ03+ily7vfPbGqFReBIbquUGSAc2+y3VNBGHfZinCV4mvJCnf7Phk1Hoo94aiJM&#13;
-kR9FvymUojUXqiFzsiockTRhvY1LoATiTBJj0NNO4RyyFSsDHcfmVcpApPv60fpdpYc/un6bvG81&#13;
-+ehf6ACQJloXAx72s63HOT8nsYw+gvgxxKo6fUWqiSBcim7zJZpMw/Mqf3qnKDtCdGhN4H6g5AHT&#13;
-RQDbTPaB6K7W1X7I1vYRClxo7EssVdE0hfDiJEO6iVpHfXVyfhfpT2yBq/sb8wh+Y68WVZ2CUXpE&#13;
-8jGrfx1HxUWeSv/EquvZF2jUTnRigaHIhsH7OBHCfCsaIorIAu+41wclnF27UdefgjZiWtzTn90B&#13;
-MI+x4PlM1WXSdvUlKOW92HY0LJNNfA7yjbNhCoygw3AT5RyQN1CeXJCOKedw5VhXhnCqLAx25v5Z&#13;
-WS14pMvx+NRAvqiPeey/w6Yl5KnDywt5A8vqh7Fi13PrfVMo75uj3ICeCxxbZSz6swQ5dk+kgCUN&#13;
-R/aE/odJi0lYxPurprXbq2Ws5HxSaqfroOOvEaogZEZNbYhRRcyuvO98fWg7DYZu9QfB+RuT0ptZ&#13;
-4jBcdm+UifSbYWHx6TFYmCS+wrSdd8+NYqF+fMA4FnqU8wCNxSYDfshUZzL0ftSYLDg0U0biSXyj&#13;
-nSRFaNGmM8gGlmB0t5+R9KaKHc0ZmYuAn7vvG9m0ZE/u8XGH5Y6gLi/Glk6yjnZoD/RoxkExb4fs&#13;
-pUJI3v4sn3aguO1I4sovIWfvz2l//VBQAh0YSAnzXgSJ7vaQkfOa+h6enOXtHIQcL6H32s20eZ4T&#13;
-S2+FR7QjwhT9gbLtVNTiID0oT5jYbtnS7Ix7kHSAbQVqfb9uf9VoCGb8L+s3br2NPW4HPG9c8s/l&#13;
-MSYv9+6Ps8XHq1jWGoRC7+JrR2qvre2/tlXMhneNg9eDM930UQrMmGBf+cH0xqJzzdSgj78ieJJ2&#13;
-XEeQ44kcuy8UIlHqOr138exiqPWtVW3dEGRp8RW5kkDmjdm2Nl7YNxt8Q7lDQizew2wQzYqIw7Pw&#13;
-80NmXm1yIIqlpekr8hOggPNn5iNNlsgeqYiWrbI8sFCZFGEbN7KPt+Rz+pjO7gefyGdtpudDJbWI&#13;
-0a5/l+/d6DQtXIk03+eXn/Vf4DNY8XtUqyOlzuOpww0h58ixWSzKCqu4ILBFg964PKJ6wtD1rq+9&#13;
-cb3+LwvEciryY92SGHmLTTI48kveI7XGbizUChrTfsfqrwWLmfaMW+C7Dx+aAOQKlSZAuOqBmx2x&#13;
-lIj8/zS9odYwB3oKHn8c4CcwlwDgPDFOAx5ByfUMWWHkFaIniAY9OJr9h9rXKZgGzNav2ZlF7Y8s&#13;
-wNQScGrScgvarUyp0yOQWnBMQzu1jAs2fUglRy0NdzoZtuSFIB0xHT10PTPqDFRChS/19TL3Om7G&#13;
-EYDid8Wd6gOwxzwsKimm29CJSuaUPB90u0z+iKLoMRSAeXr21jYWWLy919cyMZN53bmztdvIolht&#13;
-uUrv2WXPBzDtTIYRo+t3d5j8nrbRGKZlXdPm22R81dwGflwWIpV36+r+Hrurwv8SVz1NMGeOXI8p&#13;
-+9T8ngfF0dwy7JzZkEPxIcjtsBTdTMlx3Z5X79CaSMtip5ymBEL6pLQJbXJGh4XKyZs2/hq+MG/N&#13;
-mipGXELnzdu3f+XIINsyAWe2Zo2Xmo4L71tPXajy8aJ4d+gtreqKN5bFQMET01TeTLxokRSR3HG0&#13;
-G1v974X7xkQchTN4yNqIScpQyVPZ4S+WisZmEuIAFO2HvBsgHXggsV5LwRWnvM0j70qSPGVaLSN0&#13;
-PoPoXIcYCkw9GQdd3+kUO9qJXYi/1jjafEjHTACgBy1oqu2AiLY9KKolj1Wg/yXHnv4HWsxU7K1z&#13;
-gDq6foSgoh5xDp65CPCsDrkQwPDsSQpbTA5z72ZZTW7qegzVaVGnMGIZvUfsHkq/NghKjOD3eUfQ&#13;
-BDpTvZx1uGkUc4hPduSck373OHhRa7HnImPLucjbTggw3tIfcjb7km9O+G/3QxFAVquUTYCUaDzS&#13;
-qllQFkSj/SrCkm6Ofb5b3HlXQqeD1AT1karQAcy2U0E43JNmbuVtX340/dLxzPEFBZDyoZCGhTd8&#13;
-mE34eA4kGkWd3UJlCYxmhUh8JWhXyUoV8qg8Gy+5DK/WZFkYVgPeIkmMEq97/+joxnlqJyUU5Xvo&#13;
-evBuM7vEYHM85uQAHvv3ENd+3eE3PJBtcSt0qSD7ZjiypdhhvKNNz5u+zQZwCYMfXLXfr/k8LJHG&#13;
-GL4c0Qu1IkQ4JXaV3efvRtUM3s+dXGrhnpg1Fv/2K4/SZR+vORNWfjCewfS13f4OgdKOcp9aFWln&#13;
-qjf/9pwHwI51ksJ4w5lNqcAndx4y4ov+PakYAMUHjuOhkOqes5ywTVMHgX56a1Nlh0fJ0zJickIw&#13;
-pHTMJicUA6Tj+Zo=</xenc:CipherValue>
-    </xenc:CipherData>
-</xenc:EncryptedData>
\ No newline at end of file
diff --git a/src/test/java/de/ozgcloud/xta/test/app/ApplicationTests.java b/src/test/java/de/ozgcloud/xta/test/app/ApplicationITCase.java
similarity index 77%
rename from src/test/java/de/ozgcloud/xta/test/app/ApplicationTests.java
rename to src/test/java/de/ozgcloud/xta/test/app/ApplicationITCase.java
index 955b0098fbdf30bcb2aba455afd33525b8877e49..01e4b9d732d2ac72bceb5b069e9e09fd09dd490a 100644
--- a/src/test/java/de/ozgcloud/xta/test/app/ApplicationTests.java
+++ b/src/test/java/de/ozgcloud/xta/test/app/ApplicationITCase.java
@@ -2,12 +2,14 @@ package de.ozgcloud.xta.test.app;
 
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.ActiveProfiles;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 
 @ExtendWith(SpringExtension.class)
 @ActiveProfiles("test")
-class ApplicationTests {
+@SpringBootTest
+class ApplicationITCase {
 
 	@Test
 	void contextLoads() { // NOSONAR
diff --git a/src/test/java/de/ozgcloud/xta/test/app/TestingApplication.java b/src/test/java/de/ozgcloud/xta/test/app/TestingApplication.java
deleted file mode 100644
index 699efb75c3bb2d4728c9e3b1a1b317877bf5b398..0000000000000000000000000000000000000000
--- a/src/test/java/de/ozgcloud/xta/test/app/TestingApplication.java
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Created 2022-02-06
- */
-package de.ozgcloud.xta.test.app;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.context.annotation.Profile;
-
-@Profile({ "test" })
-@SpringBootApplication
-public class TestingApplication {
-
-	public static void main(final String[] args) {
-		SpringApplication.run(TestingApplication.class, args);
-	}
-}
diff --git a/src/test/java/de/ozgcloud/xta/test/app/data/XtaMessageRepositoryTest.java b/src/test/java/de/ozgcloud/xta/test/app/data/XtaMessageRepositoryTest.java
index 9aca5302125f5629e9c99543858c0ac7b6c7abee..af7fe1a6223ca4bac704049b2f28896fae44bf42 100644
--- a/src/test/java/de/ozgcloud/xta/test/app/data/XtaMessageRepositoryTest.java
+++ b/src/test/java/de/ozgcloud/xta/test/app/data/XtaMessageRepositoryTest.java
@@ -1,7 +1,7 @@
 package de.ozgcloud.xta.test.app.data;
 
-import static de.ozgcloud.xta.test.app.mapper.XtaMessageTestFactory.*;
-import static de.ozgcloud.xta.test.app.service.XtaMessageMetaDataTestFactory.*;
+import static de.ozgcloud.xta.test.app.factory.XtaMessageMetaDataTestFactory.*;
+import static de.ozgcloud.xta.test.app.factory.XtaMessageTestFactory.*;
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
 
@@ -17,12 +17,12 @@ import org.junit.jupiter.params.provider.ValueSource;
 import org.mockito.InjectMocks;
 import org.mockito.Spy;
 
-import de.ozgcloud.xta.test.app.mapper.XtaFileTestFactory;
-import de.ozgcloud.xta.test.app.mapper.XtaMessageTestFactory;
-import de.ozgcloud.xta.test.app.model.Identifier;
+import de.ozgcloud.xta.test.app.factory.XtaFileTestFactory;
+import de.ozgcloud.xta.test.app.factory.XtaMessageMetaDataTestFactory;
+import de.ozgcloud.xta.test.app.factory.XtaMessageTestFactory;
 import de.ozgcloud.xta.test.app.model.XtaFile;
+import de.ozgcloud.xta.test.app.model.XtaIdentifier;
 import de.ozgcloud.xta.test.app.model.XtaMessage;
-import de.ozgcloud.xta.test.app.service.XtaMessageMetaDataTestFactory;
 
 public class XtaMessageRepositoryTest {
 
@@ -87,6 +87,13 @@ public class XtaMessageRepositoryTest {
 			xtaMessageRepository.save(message);
 		}
 
+		@Test
+		void shouldDeleteMessage() {
+			xtaMessageRepository.delete(MESSAGE_ID);
+
+			assertThat(xtaMessageRepository.get(MESSAGE_ID)).isEmpty();
+		}
+
 		@Test
 		void shouldDeleteTemporaryFiles() {
 			assertThat(messageFile.file()).exists();
@@ -170,7 +177,7 @@ public class XtaMessageRepositoryTest {
 			xtaMessageRepository.save(XtaMessageTestFactory.create("3"));
 			xtaMessageRepository.save(XtaMessageTestFactory.createBuilder()
 					.metaData(XtaMessageMetaDataTestFactory.createBuilder()
-							.readerIdentifier(Identifier.builder().value(OTHER_READER_IDENTIFIER).build())
+							.readerIdentifier(XtaIdentifier.builder().value(OTHER_READER_IDENTIFIER).build())
 							.build())
 					.build());
 		}
diff --git a/src/test/java/de/ozgcloud/xta/test/app/service/AttributedURITypeTestFactory.java b/src/test/java/de/ozgcloud/xta/test/app/factory/AttributedURITypeTestFactory.java
similarity index 86%
rename from src/test/java/de/ozgcloud/xta/test/app/service/AttributedURITypeTestFactory.java
rename to src/test/java/de/ozgcloud/xta/test/app/factory/AttributedURITypeTestFactory.java
index b973cb6ff4c3cae9afc5b0ba0c61aeb14dcf842e..df9a5d1a6fb3ac1794e72c1962f1b77688fa3f30 100644
--- a/src/test/java/de/ozgcloud/xta/test/app/service/AttributedURITypeTestFactory.java
+++ b/src/test/java/de/ozgcloud/xta/test/app/factory/AttributedURITypeTestFactory.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.xta.test.app.service;
+package de.ozgcloud.xta.test.app.factory;
 
 import org.apache.cxf.ws.addressing.AttributedURIType;
 
diff --git a/src/test/java/de/ozgcloud/xta/test/app/service/ContentTypeTestFactory.java b/src/test/java/de/ozgcloud/xta/test/app/factory/ContentTypeTestFactory.java
similarity index 97%
rename from src/test/java/de/ozgcloud/xta/test/app/service/ContentTypeTestFactory.java
rename to src/test/java/de/ozgcloud/xta/test/app/factory/ContentTypeTestFactory.java
index 000f764f90f0abb1a09acf45d5cb5a320ae674cf..07fd09c5f25128351d858e367a9a5e0df4d54778 100644
--- a/src/test/java/de/ozgcloud/xta/test/app/service/ContentTypeTestFactory.java
+++ b/src/test/java/de/ozgcloud/xta/test/app/factory/ContentTypeTestFactory.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.xta.test.app.service;
+package de.ozgcloud.xta.test.app.factory;
 
 import java.io.File;
 import java.math.BigInteger;
diff --git a/src/test/java/de/ozgcloud/xta/test/app/service/GenericContentContainerTestFactoy.java b/src/test/java/de/ozgcloud/xta/test/app/factory/GenericContentContainerTestFactory.java
similarity index 80%
rename from src/test/java/de/ozgcloud/xta/test/app/service/GenericContentContainerTestFactoy.java
rename to src/test/java/de/ozgcloud/xta/test/app/factory/GenericContentContainerTestFactory.java
index 8048de72f5de81c761cbb9146d46ba6f2d1f2fdd..6f08e2b03d0bf8ce15a6538952ce5073645a6bc8 100644
--- a/src/test/java/de/ozgcloud/xta/test/app/service/GenericContentContainerTestFactoy.java
+++ b/src/test/java/de/ozgcloud/xta/test/app/factory/GenericContentContainerTestFactory.java
@@ -1,8 +1,8 @@
-package de.ozgcloud.xta.test.app.service;
+package de.ozgcloud.xta.test.app.factory;
 
 import genv3.de.xoev.transport.xta.x211.GenericContentContainer;
 
-public class GenericContentContainerTestFactoy {
+public class GenericContentContainerTestFactory {
 	public static GenericContentContainer create() {
 		var genericContentContainer = new GenericContentContainer();
 		var contentContainer = genericContentContainer.getContentContainer();
diff --git a/src/test/java/de/ozgcloud/xta/test/app/factory/LookupServiceRequestTestFactory.java b/src/test/java/de/ozgcloud/xta/test/app/factory/LookupServiceRequestTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..0c083b256a432314f357172b87486d5d3dc6c218
--- /dev/null
+++ b/src/test/java/de/ozgcloud/xta/test/app/factory/LookupServiceRequestTestFactory.java
@@ -0,0 +1,39 @@
+package de.ozgcloud.xta.test.app.factory;
+
+import static de.ozgcloud.xta.test.app.factory.PartyIdentifierTypeTestFactory.*;
+
+import genv3.de.xoev.transport.xta.x211.LookupServiceRequest;
+import genv3.de.xoev.transport.xta.x211.LookupServiceType;
+import genv3.eu.osci.ws.x2014.x10.transport.PartyType;
+
+public class LookupServiceRequestTestFactory {
+	public static final String SERVICE_TYPE = "http://www.osci.de/xmeld181/xmeld181Rueckmeldung.wsdl";
+	public static final PartyType READER_PARTY_TYPE = createReaderPartyType();
+
+	public static LookupServiceRequest create() {
+		var lookupServiceRequest = new LookupServiceRequest();
+		lookupServiceRequest.getLookupServiceRequestList()
+				.add(createLookupServiceRequestList());
+
+		return lookupServiceRequest;
+	}
+
+	private static LookupServiceRequest.LookupServiceRequestList createLookupServiceRequestList() {
+		var lookupServiceRequestList = new LookupServiceRequest.LookupServiceRequestList();
+		lookupServiceRequestList.setLookupService(createLookupServiceType());
+		return lookupServiceRequestList;
+	}
+
+	private static LookupServiceType createLookupServiceType() {
+		var lookupServiceType = new LookupServiceType();
+		lookupServiceType.setReader(READER_PARTY_TYPE);
+		lookupServiceType.setServiceType(SERVICE_TYPE);
+		return lookupServiceType;
+	}
+
+	private static PartyType createReaderPartyType() {
+		var readerPartyType = new PartyType();
+		readerPartyType.setIdentifier(READER_PARTY_IDENTIFIER);
+		return readerPartyType;
+	}
+}
diff --git a/src/test/java/de/ozgcloud/xta/test/app/service/MessageMetaDataTestFactory.java b/src/test/java/de/ozgcloud/xta/test/app/factory/MessageMetaDataTestFactory.java
similarity index 68%
rename from src/test/java/de/ozgcloud/xta/test/app/service/MessageMetaDataTestFactory.java
rename to src/test/java/de/ozgcloud/xta/test/app/factory/MessageMetaDataTestFactory.java
index 3d2037dcc3ccbdd4739872429b36890cb2eaeaf0..99db136548c538dbd89ef4b43e51f0a43d7e65cb 100644
--- a/src/test/java/de/ozgcloud/xta/test/app/service/MessageMetaDataTestFactory.java
+++ b/src/test/java/de/ozgcloud/xta/test/app/factory/MessageMetaDataTestFactory.java
@@ -1,4 +1,6 @@
-package de.ozgcloud.xta.test.app.service;
+package de.ozgcloud.xta.test.app.factory;
+
+import static de.ozgcloud.xta.test.app.factory.PartyIdentifierTypeTestFactory.*;
 
 import java.math.BigInteger;
 
@@ -6,23 +8,20 @@ import org.apache.cxf.ws.addressing.AttributedURIType;
 
 import genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData;
 import genv3.eu.osci.ws.x2014.x10.transport.MsgIdentificationType;
-import genv3.eu.osci.ws.x2014.x10.transport.PartyIdentifierType;
 import genv3.eu.osci.ws.x2014.x10.transport.QualifierType;
 
 public class MessageMetaDataTestFactory {
-	public static final BigInteger MESSAGE_SIZE = BigInteger.TEN;
+	public static final BigInteger MESSAGE_SIZE = BigInteger.valueOf(3000);
 	public static final String QUALIFER_SERVICE = "service";
 	public static final String QUALIFER_SUBJECT = "subject";
 	public static final String QUALIFER_MESSAGE_TYPE_CODE = "code";
 	public static final String QUALIFER_MESSAGE_TYPE_PAYLOAD_SCHEMA = "payloadSchema";
 	public static final String MESSAGE_ID = "de:xta:messageid:test-id";
-	public static final PartyIdentifierType AUTHOR_IDENTIFIER = createPartyIdentifierType("author", "AUTHOR");
-	public static final PartyIdentifierType READER_IDENTIFIER = createPartyIdentifierType("reader", "READER");
 
 	public static MessageMetaData create() {
 		var metaData = new MessageMetaData();
-		metaData.getOriginators().getAuthor().setIdentifier(AUTHOR_IDENTIFIER);
-		metaData.getDestinations().getReader().setIdentifier(READER_IDENTIFIER);
+		metaData.getOriginators().getAuthor().setIdentifier(AUTHOR_PARTY_IDENTIFIER);
+		metaData.getDestinations().getReader().setIdentifier(READER_PARTY_IDENTIFIER);
 		metaData.setMsgIdentification(createMsgIdentificationType(AttributedURITypeTestFactory.create(MESSAGE_ID)));
 		metaData.setQualifier(createQualifierType(new QualifierType.BusinessScenario()));
 		metaData.setMsgSize(MESSAGE_SIZE);
@@ -51,13 +50,4 @@ public class MessageMetaDataTestFactory {
 
 		return messageType;
 	}
-
-	private static PartyIdentifierType createPartyIdentifierType(String value, String category) {
-		var partyIdentifierType = new PartyIdentifierType();
-		partyIdentifierType.setName(value);
-		partyIdentifierType.setValue(value);
-		partyIdentifierType.setType("xoev");
-		partyIdentifierType.setCategory(category);
-		return partyIdentifierType;
-	}
 }
diff --git a/src/test/java/de/ozgcloud/xta/test/app/factory/MsgBoxCloseRequestTypeTestFactory.java b/src/test/java/de/ozgcloud/xta/test/app/factory/MsgBoxCloseRequestTypeTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..a3cd76e64a66669286222fb39cc949d5aba9776a
--- /dev/null
+++ b/src/test/java/de/ozgcloud/xta/test/app/factory/MsgBoxCloseRequestTypeTestFactory.java
@@ -0,0 +1,13 @@
+package de.ozgcloud.xta.test.app.factory;
+
+import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxCloseRequestType;
+
+public class MsgBoxCloseRequestTypeTestFactory {
+	public static final String CLOSE_REQUEST_MESSAGE_ID = "de:xta:messageid:xta-test-server:close-id";
+
+	public static MsgBoxCloseRequestType create() {
+		var closeRequest = new MsgBoxCloseRequestType();
+		closeRequest.getLastMsgReceived().add(AttributedURITypeTestFactory.create(CLOSE_REQUEST_MESSAGE_ID));
+		return closeRequest;
+	}
+}
diff --git a/src/test/java/de/ozgcloud/xta/test/app/factory/MsgBoxFetchRequestTestFactory.java b/src/test/java/de/ozgcloud/xta/test/app/factory/MsgBoxFetchRequestTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..94b619d19e5e5deb79dd0502a6685cee1ee44775
--- /dev/null
+++ b/src/test/java/de/ozgcloud/xta/test/app/factory/MsgBoxFetchRequestTestFactory.java
@@ -0,0 +1,16 @@
+package de.ozgcloud.xta.test.app.factory;
+
+import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxFetchRequest;
+import genv3.eu.osci.ws.x2008.x05.transport.MsgSelector;
+
+public class MsgBoxFetchRequestTestFactory {
+	public static final String GET_MESSAGE_REQUEST_MESSAGE_ID = "urn:de:xta:messageId:xta-test-server:1234";
+
+	public static MsgBoxFetchRequest create() {
+		MsgBoxFetchRequest fetchRequest = new MsgBoxFetchRequest();
+		MsgSelector msgSelector = new MsgSelector();
+		msgSelector.getMessageID().add(AttributedURITypeTestFactory.create(GET_MESSAGE_REQUEST_MESSAGE_ID));
+		fetchRequest.setMsgSelector(msgSelector);
+		return fetchRequest;
+	}
+}
diff --git a/src/test/java/de/ozgcloud/xta/test/app/service/MsgBoxStatusListRequestTypeTestFactory.java b/src/test/java/de/ozgcloud/xta/test/app/factory/MsgBoxStatusListRequestTypeTestFactory.java
similarity index 79%
rename from src/test/java/de/ozgcloud/xta/test/app/service/MsgBoxStatusListRequestTypeTestFactory.java
rename to src/test/java/de/ozgcloud/xta/test/app/factory/MsgBoxStatusListRequestTypeTestFactory.java
index 4660f13c334294684bdc9389ebe6c9d4cca6d379..414113230bfaab9cebb4f7fb4ce17ff224ee0d5f 100644
--- a/src/test/java/de/ozgcloud/xta/test/app/service/MsgBoxStatusListRequestTypeTestFactory.java
+++ b/src/test/java/de/ozgcloud/xta/test/app/factory/MsgBoxStatusListRequestTypeTestFactory.java
@@ -1,11 +1,11 @@
-package de.ozgcloud.xta.test.app.service;
+package de.ozgcloud.xta.test.app.factory;
 
 import java.math.BigInteger;
 
 import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxStatusListRequestType;
 
 public class MsgBoxStatusListRequestTypeTestFactory {
-	public static final String LIST_FORM = "statusList";
+	public static final String LIST_FORM = "MessageMetaData";
 
 	public static MsgBoxStatusListRequestType create(long maxListItems) {
 		var request = new MsgBoxStatusListRequestType();
diff --git a/src/test/java/de/ozgcloud/xta/test/app/factory/PartyIdentifierTypeTestFactory.java b/src/test/java/de/ozgcloud/xta/test/app/factory/PartyIdentifierTypeTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..6f33f6da90ad140b26589505afb3da0cfcacea11
--- /dev/null
+++ b/src/test/java/de/ozgcloud/xta/test/app/factory/PartyIdentifierTypeTestFactory.java
@@ -0,0 +1,25 @@
+package de.ozgcloud.xta.test.app.factory;
+
+import genv3.eu.osci.ws.x2014.x10.transport.PartyIdentifierType;
+
+public class PartyIdentifierTypeTestFactory {
+	public static final String PARTY_IDENTIFIER_TYPE = "xoev";
+	public static final String PARTY_IDENTIFIER_CATEGORY_READER = "READER-category";
+	public static final String PARTY_IDENTIFIER_NAME_READER = "READER-name";
+	public static final String PARTY_IDENTIFIER_VALUE_READER = "READER-value";
+	public static final String PARTY_IDENTIFIER_CATEGORY_AUTHOR = "AUTHOR-category";
+	public static final String PARTY_IDENTIFIER_NAME_AUTHOR = "AUTHOR-name";
+	public static final String PARTY_IDENTIFIER_VALUE_AUTHOR = "AUTHOR-value";
+
+	public static final PartyIdentifierType AUTHOR_PARTY_IDENTIFIER = create(PARTY_IDENTIFIER_VALUE_AUTHOR, PARTY_IDENTIFIER_NAME_AUTHOR, PARTY_IDENTIFIER_CATEGORY_AUTHOR);
+	public static final PartyIdentifierType READER_PARTY_IDENTIFIER = create(PARTY_IDENTIFIER_VALUE_READER, PARTY_IDENTIFIER_NAME_READER, PARTY_IDENTIFIER_CATEGORY_READER);
+
+	private static PartyIdentifierType create(String value, String name, String category) {
+		var partyIdentifierType = new PartyIdentifierType();
+		partyIdentifierType.setValue(value);
+		partyIdentifierType.setName(name);
+		partyIdentifierType.setCategory(category);
+		partyIdentifierType.setType(PARTY_IDENTIFIER_TYPE);
+		return partyIdentifierType;
+	}
+}
diff --git a/src/test/java/de/ozgcloud/xta/test/app/factory/PartyTypeTestFactory.java b/src/test/java/de/ozgcloud/xta/test/app/factory/PartyTypeTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..ab1da303c5182f304515c6a4080408b6d58d34d3
--- /dev/null
+++ b/src/test/java/de/ozgcloud/xta/test/app/factory/PartyTypeTestFactory.java
@@ -0,0 +1,20 @@
+package de.ozgcloud.xta.test.app.factory;
+
+import static de.ozgcloud.xta.test.app.factory.PartyIdentifierTypeTestFactory.*;
+
+import genv3.eu.osci.ws.x2014.x10.transport.PartyType;
+
+public class PartyTypeTestFactory {
+
+	public static PartyType create() {
+		var partyIdentifier = new PartyType();
+		partyIdentifier.setIdentifier(READER_PARTY_IDENTIFIER);
+		return partyIdentifier;
+	}
+
+	public static PartyType createWithAuthor() {
+		var partyIdentifier = new PartyType();
+		partyIdentifier.setIdentifier(AUTHOR_PARTY_IDENTIFIER);
+		return partyIdentifier;
+	}
+}
diff --git a/src/test/java/de/ozgcloud/xta/test/app/service/QualifierTypeBusinessScenarioTestFactory.java b/src/test/java/de/ozgcloud/xta/test/app/factory/QualifierTypeBusinessScenarioTestFactory.java
similarity index 96%
rename from src/test/java/de/ozgcloud/xta/test/app/service/QualifierTypeBusinessScenarioTestFactory.java
rename to src/test/java/de/ozgcloud/xta/test/app/factory/QualifierTypeBusinessScenarioTestFactory.java
index 7150e8c6e30b40440cc7084011efefd9d15cd66b..4dd3aa0d17657e873580b1cab5f2ae8e58a96e3a 100644
--- a/src/test/java/de/ozgcloud/xta/test/app/service/QualifierTypeBusinessScenarioTestFactory.java
+++ b/src/test/java/de/ozgcloud/xta/test/app/factory/QualifierTypeBusinessScenarioTestFactory.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.xta.test.app.service;
+package de.ozgcloud.xta.test.app.factory;
 
 import genv3.eu.osci.ws.x2014.x10.transport.QualifierType;
 
diff --git a/src/test/java/de/ozgcloud/xta/test/app/service/TempFileTestFactory.java b/src/test/java/de/ozgcloud/xta/test/app/factory/TempFileTestFactory.java
similarity index 90%
rename from src/test/java/de/ozgcloud/xta/test/app/service/TempFileTestFactory.java
rename to src/test/java/de/ozgcloud/xta/test/app/factory/TempFileTestFactory.java
index b2b501432516604b312019f1b79a1029daa69a03..13df5bf390a28069702d7d437a0e23870d03ef93 100644
--- a/src/test/java/de/ozgcloud/xta/test/app/service/TempFileTestFactory.java
+++ b/src/test/java/de/ozgcloud/xta/test/app/factory/TempFileTestFactory.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.xta.test.app.service;
+package de.ozgcloud.xta.test.app.factory;
 
 import java.io.File;
 import java.nio.charset.StandardCharsets;
diff --git a/src/test/java/de/ozgcloud/xta/test/app/factory/XtaCloseRequestTestFactory.java b/src/test/java/de/ozgcloud/xta/test/app/factory/XtaCloseRequestTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..4c787394927f131fae3762d0346cd7f845b23687
--- /dev/null
+++ b/src/test/java/de/ozgcloud/xta/test/app/factory/XtaCloseRequestTestFactory.java
@@ -0,0 +1,20 @@
+package de.ozgcloud.xta.test.app.factory;
+
+import static de.ozgcloud.xta.test.app.factory.XtaMessageMetaDataTestFactory.*;
+
+import de.ozgcloud.xta.test.app.model.XtaCloseRequest;
+
+public class XtaCloseRequestTestFactory {
+
+	public static final String CLOSE_REQUEST_MESSAGE_ID = "close-request-message-id";
+
+	public static XtaCloseRequest create() {
+		return createBuilder().build();
+	}
+
+	public static XtaCloseRequest.XtaCloseRequestBuilder createBuilder() {
+		return XtaCloseRequest.builder()
+				.messageId(CLOSE_REQUEST_MESSAGE_ID)
+				.clientIdentifier(READER_IDENTIFIER);
+	}
+}
diff --git a/src/test/java/de/ozgcloud/xta/test/app/mapper/XtaFileTestFactory.java b/src/test/java/de/ozgcloud/xta/test/app/factory/XtaFileTestFactory.java
similarity index 58%
rename from src/test/java/de/ozgcloud/xta/test/app/mapper/XtaFileTestFactory.java
rename to src/test/java/de/ozgcloud/xta/test/app/factory/XtaFileTestFactory.java
index fca7978e6fab2db263bd15d0469dcd64bf391774..0e89e8e12996a1a088aea5c5dc817f3e194010fc 100644
--- a/src/test/java/de/ozgcloud/xta/test/app/mapper/XtaFileTestFactory.java
+++ b/src/test/java/de/ozgcloud/xta/test/app/factory/XtaFileTestFactory.java
@@ -1,21 +1,20 @@
-package de.ozgcloud.xta.test.app.mapper;
+package de.ozgcloud.xta.test.app.factory;
 
 import java.io.File;
 import java.math.BigInteger;
 
 import de.ozgcloud.xta.test.app.model.XtaFile;
-import de.ozgcloud.xta.test.app.service.TempFileTestFactory;
 
 public class XtaFileTestFactory {
-	static final String NAME = "Test_File";
-	static final String XTA_CONTENT = "slkafj3jifsdasx";
-	static final String ZIP_CONTENT_TYPE = "application/zip";
+	public static final String NAME = "Test_File";
+	public static final String XTA_CONTENT = "slkafj3jifsdasx";
+	public static final String ZIP_CONTENT_TYPE = "application/zip";
 
 	public static XtaFile create() {
 		return createBuilder().build();
 	}
 
-	static XtaFile.XtaFileBuilder createBuilder() {
+	public static XtaFile.XtaFileBuilder createBuilder() {
 		File tfile = TempFileTestFactory.createFile(XTA_CONTENT);
 		return XtaFile.builder()
 				.name(NAME)
diff --git a/src/test/java/de/ozgcloud/xta/test/app/factory/XtaGetMessageRequestTestFactory.java b/src/test/java/de/ozgcloud/xta/test/app/factory/XtaGetMessageRequestTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..0e3426c89f76604a1202eac54fc0eccf106573ee
--- /dev/null
+++ b/src/test/java/de/ozgcloud/xta/test/app/factory/XtaGetMessageRequestTestFactory.java
@@ -0,0 +1,19 @@
+package de.ozgcloud.xta.test.app.factory;
+
+import static de.ozgcloud.xta.test.app.factory.XtaMessageMetaDataTestFactory.*;
+
+import de.ozgcloud.xta.test.app.model.XtaGetMessageRequest;
+
+public class XtaGetMessageRequestTestFactory {
+	public static final String VALID_MESSAGE_ID = "urn:de:xta:messageid:application:000ca2fe-f4e1-45c2-8233-3a0eb760bd16";
+
+	public static XtaGetMessageRequest.XtaGetMessageRequestBuilder createBuilder() {
+		return XtaGetMessageRequest.builder()
+				.messageId(VALID_MESSAGE_ID)
+				.clientIdentifier(READER_IDENTIFIER);
+	}
+
+	public static XtaGetMessageRequest create() {
+		return createBuilder().build();
+	}
+}
diff --git a/src/test/java/de/ozgcloud/xta/test/app/factory/XtaLookupServiceRequestTestFactory.java b/src/test/java/de/ozgcloud/xta/test/app/factory/XtaLookupServiceRequestTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..32f798491dd93f9f9a6e3114da3b5b6bd7032db6
--- /dev/null
+++ b/src/test/java/de/ozgcloud/xta/test/app/factory/XtaLookupServiceRequestTestFactory.java
@@ -0,0 +1,21 @@
+package de.ozgcloud.xta.test.app.factory;
+
+import static de.ozgcloud.xta.test.app.factory.XtaMessageMetaDataTestFactory.*;
+
+import de.ozgcloud.xta.test.app.model.XtaLookupServiceRequest;
+
+public class XtaLookupServiceRequestTestFactory {
+
+	public static String LOOKUP_SERVICE_SERVICE = "lookup-request-service";
+
+	public static XtaLookupServiceRequest create() {
+		return createBuilder().build();
+	}
+
+	public static XtaLookupServiceRequest.XtaLookupServiceRequestBuilder createBuilder() {
+		return XtaLookupServiceRequest.builder()
+				.service(LOOKUP_SERVICE_SERVICE)
+				.readerIdentifier(READER_IDENTIFIER)
+				.authorIdentifier(AUTHOR_IDENTIFIER);
+	}
+}
diff --git a/src/test/java/de/ozgcloud/xta/test/app/service/XtaMessageMetaDataTestFactory.java b/src/test/java/de/ozgcloud/xta/test/app/factory/XtaMessageMetaDataTestFactory.java
similarity index 68%
rename from src/test/java/de/ozgcloud/xta/test/app/service/XtaMessageMetaDataTestFactory.java
rename to src/test/java/de/ozgcloud/xta/test/app/factory/XtaMessageMetaDataTestFactory.java
index 8760cc8b3dc309ebb3ef40d5f5eae7239ca40b1c..b6cdda74d9d0c96ac677e933a240592b4fecc9db 100644
--- a/src/test/java/de/ozgcloud/xta/test/app/service/XtaMessageMetaDataTestFactory.java
+++ b/src/test/java/de/ozgcloud/xta/test/app/factory/XtaMessageMetaDataTestFactory.java
@@ -1,14 +1,23 @@
-package de.ozgcloud.xta.test.app.service;
+package de.ozgcloud.xta.test.app.factory;
 
-import java.math.BigInteger;
+import static de.ozgcloud.xta.test.app.factory.MessageMetaDataTestFactory.*;
+import static de.ozgcloud.xta.test.app.factory.PartyIdentifierTypeTestFactory.*;
 
-import de.ozgcloud.xta.test.app.model.Identifier;
+import de.ozgcloud.xta.test.app.model.XtaIdentifier;
 import de.ozgcloud.xta.test.app.model.XtaMessageMetaData;
 
 public class XtaMessageMetaDataTestFactory {
 	public static final String DEFAULT_MESSAGE_ID = "defaultMessageId";
-	public static final Identifier AUTHOR_IDENTIFIER = createIdentifier("author", "AUTHOR");
-	public static final Identifier READER_IDENTIFIER = createIdentifier("reader", "READER");
+	public static final XtaIdentifier AUTHOR_IDENTIFIER = XtaIdentifier.builder()
+			.value(PARTY_IDENTIFIER_VALUE_AUTHOR)
+			.name(PARTY_IDENTIFIER_NAME_AUTHOR)
+			.category(PARTY_IDENTIFIER_CATEGORY_AUTHOR)
+			.build();
+	public static final XtaIdentifier READER_IDENTIFIER = XtaIdentifier.builder()
+			.value(PARTY_IDENTIFIER_VALUE_READER)
+			.name(PARTY_IDENTIFIER_NAME_READER)
+			.category(PARTY_IDENTIFIER_CATEGORY_READER)
+			.build();
 	public static final String SERVICE = "Service";
 	public static final String BUSINESS_SCENARIO_CODE = "BusinessScenarioCode";
 	public static final String BUSINESS_SCENARIO_NAME = "BusinessScenarioName";
@@ -16,7 +25,6 @@ public class XtaMessageMetaDataTestFactory {
 	public static final String BUSINESS_SCENARIO_LIST_VERSION_ID = "BusinessScenarioListVersionID";
 	public static final String MESSAGE_TYPE_CODE = "MessageTypeCode";
 	public static final String MESSAGE_PAYLOAD_SCHEMA = "MessageTypePayloadSchema";
-	public static final BigInteger MESSAGE_SIZE = BigInteger.valueOf(3000);
 
 	public static XtaMessageMetaData create() {
 		return createBuilder().build();
@@ -43,11 +51,4 @@ public class XtaMessageMetaDataTestFactory {
 				.messageSize(MESSAGE_SIZE);
 	}
 
-	private static Identifier createIdentifier(String value, String category) {
-		return Identifier.builder()
-				.value(value)
-				.name(value)
-				.category(category)
-				.build();
-	}
 }
diff --git a/src/test/java/de/ozgcloud/xta/test/app/mapper/XtaMessageTestFactory.java b/src/test/java/de/ozgcloud/xta/test/app/factory/XtaMessageTestFactory.java
similarity index 88%
rename from src/test/java/de/ozgcloud/xta/test/app/mapper/XtaMessageTestFactory.java
rename to src/test/java/de/ozgcloud/xta/test/app/factory/XtaMessageTestFactory.java
index 81ac3daa5520f0d4413ad0c1b9e5d964a7f1b4f9..d1f628163b067b0401b3d5e5394fcc5659640b11 100644
--- a/src/test/java/de/ozgcloud/xta/test/app/mapper/XtaMessageTestFactory.java
+++ b/src/test/java/de/ozgcloud/xta/test/app/factory/XtaMessageTestFactory.java
@@ -1,9 +1,8 @@
-package de.ozgcloud.xta.test.app.mapper;
+package de.ozgcloud.xta.test.app.factory;
 
 import java.util.List;
 
 import de.ozgcloud.xta.test.app.model.XtaMessage;
-import de.ozgcloud.xta.test.app.service.XtaMessageMetaDataTestFactory;
 
 public class XtaMessageTestFactory {
 	public static final String MESSAGE_ID_1 = "status_1";
@@ -26,4 +25,4 @@ public class XtaMessageTestFactory {
 				.messageFile(XtaFileTestFactory.create())
 				.attachmentFiles(List.of(XtaFileTestFactory.create()));
 	}
-}
+}
\ No newline at end of file
diff --git a/src/test/java/de/ozgcloud/xta/test/app/mapper/ExceptionMapperTest.java b/src/test/java/de/ozgcloud/xta/test/app/mapper/ExceptionMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..4279ef93590c87f083ba661fcd70e6287c2ff46b
--- /dev/null
+++ b/src/test/java/de/ozgcloud/xta/test/app/mapper/ExceptionMapperTest.java
@@ -0,0 +1,140 @@
+package de.ozgcloud.xta.test.app.mapper;
+
+import static de.ozgcloud.xta.test.app.mapper.ExceptionMapper.*;
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+
+import genv3.de.xoev.transport.xta.x211.InvalidMessageIDException;
+import genv3.de.xoev.transport.xta.x211.ParameterIsNotValidException;
+import genv3.de.xoev.transport.xta.x211.XTAWSTechnicalProblemException;
+
+class ExceptionMapperTest {
+
+	private final ExceptionMapper mapper = Mappers.getMapper(ExceptionMapper.class);
+
+	@DisplayName("create invalid message id exception")
+	@Nested
+	class TestCreateInvalidMessageIdException {
+		private final String exceptionMessage = "test message";
+
+		@DisplayName("should map message")
+		@Test
+		void shouldMapMessage() {
+			var result = createException();
+
+			assertThat(result.getMessage()).isEqualTo(exceptionMessage);
+		}
+
+		@DisplayName("should map error code")
+		@Test
+		void shouldMapErrorCode() {
+			var result = createException().getFaultInfo().getErrorCode();
+
+			assertThat(result).usingRecursiveComparison()
+					.isEqualTo(mapper.mapCodeFehlernummer(ERROR_CODE_MESSAGE_ID_UNKNOWN, ERROR_CODE_MESSAGE_ID_UNKNOWN_DESCRIPTION));
+		}
+
+		private InvalidMessageIDException createException() {
+			return mapper.createInvalidMessageIDException(exceptionMessage);
+		}
+
+	}
+
+	@DisplayName("create technical problem exception")
+	@Nested
+	class TestCreateTechnicalProblemException {
+		private final String exceptionMessage = "test message";
+
+		@DisplayName("should map message")
+		@Test
+		void shouldMapMessage() {
+			var result = createException();
+
+			assertThat(result.getMessage()).isEqualTo(exceptionMessage);
+		}
+
+		@DisplayName("should map error code")
+		@Test
+		void shouldMapErrorCode() {
+			var result = createException().getFaultInfo().getErrorCode();
+
+			assertThat(result).usingRecursiveComparison()
+					.isEqualTo(mapper.mapCodeFehlernummer(ERROR_CODE_INTERNAL_TECHNICAL_PROBLEM, ERROR_CODE_INTERNAL_TECHNICAL_PROBLEM_DESCRIPTION));
+		}
+
+		private XTAWSTechnicalProblemException createException() {
+			return mapper.createTechnicalProblemException(exceptionMessage);
+		}
+
+	}
+
+	@DisplayName("create parameter is not valid exception")
+	@Nested
+	class TestCreateParameterIsNotValidException {
+		private final String exceptionMessage = "test message";
+
+		@DisplayName("should map message")
+		@Test
+		void shouldMapMessage() {
+			var result = createException();
+
+			assertThat(result.getMessage()).isEqualTo(exceptionMessage);
+		}
+
+		@DisplayName("should map error code")
+		@Test
+		void shouldMapErrorCode() {
+			var result = createException().getFaultInfo().getErrorCode();
+
+			assertThat(result).usingRecursiveComparison()
+					.isEqualTo(mapper.mapCodeFehlernummer(ERROR_CODE_PARAMETER_MISSING, ERROR_CODE_PARAMETER_MISSING_DESCRIPTION));
+		}
+
+		private ParameterIsNotValidException createException() {
+			return mapper.createParameterIsNotValidException(exceptionMessage);
+		}
+	}
+
+	@DisplayName("map code error")
+	@Nested
+	class TestMapCodeError {
+		private final String code = "test code";
+		private final String name = "test name";
+
+		@DisplayName("should map code")
+		@Test
+		void shouldMapCode() {
+			var result = mapper.mapCodeFehlernummer(code, name);
+
+			assertThat(result.getCode()).isEqualTo(code);
+		}
+
+		@DisplayName("should map name")
+		@Test
+		void shouldMapName() {
+			var result = mapper.mapCodeFehlernummer(code, name);
+
+			assertThat(result.getName()).isEqualTo(name);
+		}
+
+		@DisplayName("should map list uri")
+		@Test
+		void shouldMapListUri() {
+			var result = mapper.mapCodeFehlernummer(code, name);
+
+			assertThat(result.getListURI()).isEqualTo(ERROR_CODE_LIST_URN);
+		}
+
+		@DisplayName("should map list version id")
+		@Test
+		void shouldMapListVersionId() {
+			var result = mapper.mapCodeFehlernummer(code, name);
+
+			assertThat(result.getListVersionID()).isEqualTo(ERROR_CODE_LIST_VERSION);
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/test/java/de/ozgcloud/xta/test/app/mapper/PartyTypeTestFactory.java b/src/test/java/de/ozgcloud/xta/test/app/mapper/PartyTypeTestFactory.java
deleted file mode 100644
index f4f6486898ee9d44073323f558972eb9b6f9ab28..0000000000000000000000000000000000000000
--- a/src/test/java/de/ozgcloud/xta/test/app/mapper/PartyTypeTestFactory.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package de.ozgcloud.xta.test.app.mapper;
-
-
-import static de.ozgcloud.xta.test.app.service.MessageMetaDataTestFactory.*;
-
-import genv3.eu.osci.ws.x2014.x10.transport.PartyIdentifierType;
-import genv3.eu.osci.ws.x2014.x10.transport.PartyType;
-
-public class PartyTypeTestFactory {
-
-	public static PartyType create() {
-		var partyIdentifier = new PartyType();
-		partyIdentifier.setIdentifier(createIdentifier());
-		return partyIdentifier;
-	}
-
-	private static PartyIdentifierType createIdentifier() {
-		var identifier = new PartyIdentifierType();
-		identifier.setName(READER_IDENTIFIER.getName());
-		identifier.setCategory(READER_IDENTIFIER.getCategory());
-		identifier.setValue(READER_IDENTIFIER.getValue());
-		return identifier;
-	}
-
-}
diff --git a/src/test/java/de/ozgcloud/xta/test/app/mapper/RequestMapperTest.java b/src/test/java/de/ozgcloud/xta/test/app/mapper/RequestMapperTest.java
index f9be2e6c0628b5b3c95a0d5dcd6a240ff83d90b6..0e6128c38f8ef5ffe70927050d5bb0715c4c8c3b 100644
--- a/src/test/java/de/ozgcloud/xta/test/app/mapper/RequestMapperTest.java
+++ b/src/test/java/de/ozgcloud/xta/test/app/mapper/RequestMapperTest.java
@@ -1,6 +1,10 @@
 package de.ozgcloud.xta.test.app.mapper;
 
-import static de.ozgcloud.xta.test.app.service.XtaMessageMetaDataTestFactory.*;
+import static de.ozgcloud.xta.test.app.factory.LookupServiceRequestTestFactory.*;
+import static de.ozgcloud.xta.test.app.factory.MsgBoxCloseRequestTypeTestFactory.*;
+import static de.ozgcloud.xta.test.app.factory.MsgBoxFetchRequestTestFactory.*;
+import static de.ozgcloud.xta.test.app.factory.PartyIdentifierTypeTestFactory.*;
+import static de.ozgcloud.xta.test.app.factory.XtaMessageMetaDataTestFactory.*;
 import static org.assertj.core.api.Assertions.*;
 
 import java.nio.file.Files;
@@ -12,19 +16,25 @@ import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mapstruct.factory.Mappers;
 
-import de.ozgcloud.xta.test.app.model.Identifier;
+import de.ozgcloud.xta.test.app.factory.AttributedURITypeTestFactory;
+import de.ozgcloud.xta.test.app.factory.ContentTypeTestFactory;
+import de.ozgcloud.xta.test.app.factory.GenericContentContainerTestFactory;
+import de.ozgcloud.xta.test.app.factory.LookupServiceRequestTestFactory;
+import de.ozgcloud.xta.test.app.factory.MessageMetaDataTestFactory;
+import de.ozgcloud.xta.test.app.factory.MsgBoxCloseRequestTypeTestFactory;
+import de.ozgcloud.xta.test.app.factory.MsgBoxFetchRequestTestFactory;
+import de.ozgcloud.xta.test.app.factory.MsgBoxStatusListRequestTypeTestFactory;
+import de.ozgcloud.xta.test.app.factory.PartyTypeTestFactory;
+import de.ozgcloud.xta.test.app.factory.QualifierTypeBusinessScenarioTestFactory;
+import de.ozgcloud.xta.test.app.model.XtaCloseRequest;
 import de.ozgcloud.xta.test.app.model.XtaFile;
+import de.ozgcloud.xta.test.app.model.XtaGetMessageRequest;
+import de.ozgcloud.xta.test.app.model.XtaIdentifier;
+import de.ozgcloud.xta.test.app.model.XtaLookupServiceRequest;
 import de.ozgcloud.xta.test.app.model.XtaMessageMetaDataListingRequest;
-import de.ozgcloud.xta.test.app.service.AttributedURITypeTestFactory;
-import de.ozgcloud.xta.test.app.service.ContentTypeTestFactory;
-import de.ozgcloud.xta.test.app.service.GenericContentContainerTestFactoy;
-import de.ozgcloud.xta.test.app.service.MessageMetaDataTestFactory;
-import de.ozgcloud.xta.test.app.service.MsgBoxStatusListRequestTypeTestFactory;
-import de.ozgcloud.xta.test.app.service.QualifierTypeBusinessScenarioTestFactory;
 import genv3.de.xoev.transport.xta.x211.ContentType;
 import genv3.de.xoev.transport.xta.x211.GenericContentContainer;
 import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxFetchRequest;
-import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxStatusListRequestType;
 import genv3.eu.osci.ws.x2008.x05.transport.MsgSelector;
 import genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData;
 import genv3.eu.osci.ws.x2014.x10.transport.PartyIdentifierType;
@@ -32,7 +42,41 @@ import lombok.SneakyThrows;
 
 public class RequestMapperTest {
 
-	private final RequestMapper requestMapper = Mappers.getMapper(RequestMapper.class);
+	private final RequestMapper mapper = Mappers.getMapper(RequestMapper.class);
+
+	@DisplayName("map XtaIdentifier")
+	@Nested
+	class TestMapXtaIdentifier {
+		private static final PartyIdentifierType CLIENT_IDENTIFIER = PartyTypeTestFactory.create().getIdentifier();
+
+		@DisplayName("should map name")
+		@Test
+		void shouldMapName() {
+			var result = doMapping();
+
+			assertThat(result.name()).isEqualTo(CLIENT_IDENTIFIER.getName());
+		}
+
+		@DisplayName("should map category")
+		@Test
+		void shouldMapCategory() {
+			var result = doMapping();
+
+			assertThat(result.category()).isEqualTo(CLIENT_IDENTIFIER.getCategory());
+		}
+
+		@DisplayName("should map value")
+		@Test
+		void shouldMapValue() {
+			var result = doMapping();
+
+			assertThat(result.value()).isEqualTo(CLIENT_IDENTIFIER.getValue());
+		}
+
+		private XtaIdentifier doMapping() {
+			return mapper.mapXtaIdentifier(CLIENT_IDENTIFIER);
+		}
+	}
 
 	@Nested
 	class MapXtaMessageFromGenericContentContainer {
@@ -44,7 +88,7 @@ public class RequestMapperTest {
 		@BeforeEach
 		void beforeEach() {
 			messageMetaData = MessageMetaDataTestFactory.create();
-			genericContentContainer = GenericContentContainerTestFactoy.create();
+			genericContentContainer = GenericContentContainerTestFactory.create();
 			messageContentType = ContentTypeTestFactory.createContentType();
 			attachmentContentType = ContentTypeTestFactory.createContentType();
 			var container = genericContentContainer.getContentContainer();
@@ -55,7 +99,7 @@ public class RequestMapperTest {
 		@DisplayName("Should map message and attachment files from content container")
 		@Test
 		void shouldMapFiles() {
-			var xtaMessage = requestMapper.mapXtaMessageFromGenericContentContainer(genericContentContainer, messageMetaData);
+			var xtaMessage = mapper.mapXtaMessageFromGenericContentContainer(genericContentContainer, messageMetaData);
 			var messageFile = xtaMessage.messageFile();
 			var attachmentFiles = xtaMessage.attachmentFiles();
 
@@ -77,7 +121,7 @@ public class RequestMapperTest {
 		@DisplayName("Should map XtaMessageMetaData from MessageMetaData")
 		@Test
 		void shouldMapMetaData() {
-			var xtaMessage = requestMapper.mapXtaMessageFromGenericContentContainer(genericContentContainer, messageMetaData);
+			var xtaMessage = mapper.mapXtaMessageFromGenericContentContainer(genericContentContainer, messageMetaData);
 			var xtaMessageMetaData = xtaMessage.metaData();
 
 			assertThat(xtaMessageMetaData.service()).isEqualTo(MessageMetaDataTestFactory.QUALIFER_SERVICE);
@@ -90,15 +134,15 @@ public class RequestMapperTest {
 		@DisplayName("Should map author and reader identifiers from MessageMetaData")
 		@Test
 		void shouldMapIdentifier() {
-			var xtaMessage = requestMapper.mapXtaMessageFromGenericContentContainer(genericContentContainer, messageMetaData);
+			var xtaMessage = mapper.mapXtaMessageFromGenericContentContainer(genericContentContainer, messageMetaData);
 			var authorIdentifier = xtaMessage.metaData().authorIdentifier();
 			var readerIdentifier = xtaMessage.metaData().readerIdentifier();
 
-			assertIdentifiersAreEqual(authorIdentifier, MessageMetaDataTestFactory.AUTHOR_IDENTIFIER);
-			assertIdentifiersAreEqual(readerIdentifier, MessageMetaDataTestFactory.READER_IDENTIFIER);
+			assertIdentifiersAreEqual(authorIdentifier, AUTHOR_PARTY_IDENTIFIER);
+			assertIdentifiersAreEqual(readerIdentifier, READER_PARTY_IDENTIFIER);
 		}
 
-		void assertIdentifiersAreEqual(Identifier identifier, PartyIdentifierType identifierType) {
+		void assertIdentifiersAreEqual(XtaIdentifier identifier, PartyIdentifierType identifierType) {
 			assertThat(identifier.name()).isEqualTo(identifierType.getName());
 			assertThat(identifier.category()).isEqualTo(identifierType.getCategory());
 			assertThat(identifier.value()).isEqualTo(identifierType.getValue());
@@ -110,12 +154,13 @@ public class RequestMapperTest {
 			var businessScenario = QualifierTypeBusinessScenarioTestFactory.createDefinedBusinessScenario();
 			messageMetaData.getQualifier().setBusinessScenario(businessScenario);
 
-			var xtaMessageMetaData = requestMapper.mapXtaMessageMetaData(messageMetaData);
+			var xtaMessageMetaData = mapper.mapXtaMessageMetaData(messageMetaData);
 
 			assertThat(xtaMessageMetaData.businessScenarioCode()).isEqualTo(QualifierTypeBusinessScenarioTestFactory.BUSINESS_SCENARIO_CODE);
 			assertThat(xtaMessageMetaData.businessScenarioName()).isEqualTo(QualifierTypeBusinessScenarioTestFactory.BUSINESS_SCENARIO_NAME);
 			assertThat(xtaMessageMetaData.businessScenarioListUri()).isEqualTo(QualifierTypeBusinessScenarioTestFactory.BUSINESS_SCENARIO_LIST_URI);
-			assertThat(xtaMessageMetaData.businessScenarioListVersionId()).isEqualTo(QualifierTypeBusinessScenarioTestFactory.BUSINESS_SCENARIO_LIST_VERSION_ID);
+			assertThat(xtaMessageMetaData.businessScenarioListVersionId()).isEqualTo(
+					QualifierTypeBusinessScenarioTestFactory.BUSINESS_SCENARIO_LIST_VERSION_ID);
 		}
 
 		@DisplayName("Should map an undefined business scenario from MessageMetaData")
@@ -124,7 +169,7 @@ public class RequestMapperTest {
 			var businessScenario = QualifierTypeBusinessScenarioTestFactory.createUndefinedBusinessScenario();
 			messageMetaData.getQualifier().setBusinessScenario(businessScenario);
 
-			var xtaMessageMetaData = requestMapper.mapXtaMessageMetaData(messageMetaData);
+			var xtaMessageMetaData = mapper.mapXtaMessageMetaData(messageMetaData);
 
 			assertThat(xtaMessageMetaData.businessScenarioCode()).isEqualTo(QualifierTypeBusinessScenarioTestFactory.BUSINESS_SCENARIO_CODE);
 			assertThat(xtaMessageMetaData.businessScenarioListUri()).isNull();
@@ -151,72 +196,133 @@ public class RequestMapperTest {
 		@DisplayName("Should map message id from MsgBoxRequest")
 		@Test
 		void shouldMapMessageId() {
-			var messageId = requestMapper.mapMessageIdFromMsgBoxFetchRequest(fetchRequest);
+			var messageId = mapper.mapMessageIdFromMsgBoxFetchRequest(fetchRequest);
 
 			assertThat(messageId).isEqualTo(MESSAGE_ID);
 		}
 	}
 
+	@DisplayName("map message meta data listing request")
 	@Nested
-	class MapMaxListItems {
-		private MsgBoxStatusListRequestType fetchRequest;
+	class TestMapMessageMetaDataListingRequest {
+		private static final int MAX_LIST_ITEMS = 10;
 
-		@DisplayName("Should map max list items from MsgBoxStatusListRequestType")
+		@DisplayName("should map client identifier")
 		@Test
-		void shouldMapMaxListItems() {
-			fetchRequest = MsgBoxStatusListRequestTypeTestFactory.create(10);
+		void shouldMapClientIdentifier() {
+			var result = doMapping();
+
+			assertThat(result.clientIdentifier())
+					.usingRecursiveComparison()
+					.isEqualTo(READER_IDENTIFIER);
+		}
 
-			var maxListItems = requestMapper.mapMaxListItems(fetchRequest);
+		@DisplayName("should map max list items")
+		@Test
+		void shouldMaxMaxListItems() {
+			var result = doMapping();
 
-			assertThat(maxListItems).isEqualTo(10);
+			assertThat(result.maxListItems()).isEqualTo(MAX_LIST_ITEMS);
 		}
 
-		@DisplayName("Should map unsupported negative max list items value to maximum integer value")
+		private XtaMessageMetaDataListingRequest doMapping() {
+			return mapper.mapMessageMetaDataListingRequest(
+					MsgBoxStatusListRequestTypeTestFactory.create(MAX_LIST_ITEMS),
+					READER_PARTY_TYPE
+			);
+		}
+	}
+
+	@DisplayName("map xta close request")
+	@Nested
+	class TestMapXtaCloseRequest {
+		@DisplayName("should map message id")
+		@Test
+		void shouldMapMessageId() {
+			var result = doMapping();
+
+			assertThat(result.messageId()).isEqualTo(CLOSE_REQUEST_MESSAGE_ID);
+		}
+
+		@DisplayName("should map client identifier")
 		@Test
-		void shouldMapMaxListItemsToMaxValue() {
-			fetchRequest = MsgBoxStatusListRequestTypeTestFactory.create(-1);
+		void shouldMapClientIdentifier() {
+			var result = doMapping();
+
+			assertThat(result.clientIdentifier())
+					.usingRecursiveComparison()
+					.isEqualTo(READER_IDENTIFIER);
+		}
 
-			var maxListItems = requestMapper.mapMaxListItems(fetchRequest);
+		private XtaCloseRequest doMapping() {
+			return mapper.mapXtaCloseRequest(MsgBoxCloseRequestTypeTestFactory.create(),
+					PartyTypeTestFactory.create());
+		}
+	}
+
+	@DisplayName("map xta get message request")
+	@Nested
+	class TestMapXtaGetMessageRequest {
+		@DisplayName("should map message id")
+		@Test
+		void shouldMapMessageId() {
+			var result = doMapping();
 
-			assertThat(maxListItems).isEqualTo(Integer.MAX_VALUE);
+			assertThat(result.messageId()).isEqualTo(GET_MESSAGE_REQUEST_MESSAGE_ID);
 		}
 
-		@DisplayName("Should map unsupported large max list items value to maximum integer value")
+		@DisplayName("should map client identifier")
 		@Test
-		void shouldMapMaxListItemsToMaxValueWhenOverflowing() {
-			fetchRequest = MsgBoxStatusListRequestTypeTestFactory.create(Long.MAX_VALUE);
+		void shouldMapClientIdentifier() {
+			var result = doMapping();
 
-			var maxListItems = requestMapper.mapMaxListItems(fetchRequest);
+			assertThat(result.clientIdentifier())
+					.usingRecursiveComparison()
+					.isEqualTo(READER_IDENTIFIER);
+		}
 
-			assertThat(maxListItems).isEqualTo(Integer.MAX_VALUE);
+		private XtaGetMessageRequest doMapping() {
+			return mapper.mapXtaGetMessageRequest(MsgBoxFetchRequestTestFactory.create(),
+					PartyTypeTestFactory.create());
 		}
 	}
 
-	@DisplayName("map message meta data listing request")
+	@DisplayName("map xta lookup service request")
 	@Nested
-	class TestMapMessageMetaDataListingRequest {
-		private static final int MAX_LIST_ITEMS = 10;
+	class TestMapXtaLookupServiceRequest {
 
-		@DisplayName("should map client identifier value")
+		@DisplayName("should map service")
 		@Test
-		void shouldMapClientIdentifierValue() {
+		void shouldMapService() {
 			var result = doMapping();
 
-			assertThat(result.clientIdentifierValue()).isEqualTo(READER_IDENTIFIER.value());
+			assertThat(result.service()).isEqualTo(SERVICE_TYPE);
 		}
 
-		@DisplayName("should map max list items")
+		@DisplayName("should map reader identifier")
 		@Test
-		void shouldMaxMaxListItems() {
+		void shouldMapReaderIdentifier() {
 			var result = doMapping();
 
-			assertThat(result.maxListItems()).isEqualTo(MAX_LIST_ITEMS);
+			assertThat(result.readerIdentifier())
+					.usingRecursiveComparison()
+					.isEqualTo(READER_IDENTIFIER);
 		}
 
-		private XtaMessageMetaDataListingRequest doMapping() {
-			return requestMapper.mapMessageMetaDataListingRequest(MsgBoxStatusListRequestTypeTestFactory.create(MAX_LIST_ITEMS), PartyTypeTestFactory.create());
+		@DisplayName("should map author identifier value")
+		@Test
+		void shouldMapAuthorIdentifierValue() {
+			var result = doMapping();
+
+			assertThat(result.authorIdentifier())
+					.usingRecursiveComparison()
+					.isEqualTo(AUTHOR_IDENTIFIER);
 		}
 
+		private XtaLookupServiceRequest doMapping() {
+			return mapper.mapXtaLookupServiceRequest(LookupServiceRequestTestFactory.create(),
+					PartyTypeTestFactory.createWithAuthor());
+		}
 	}
 
 }
diff --git a/src/test/java/de/ozgcloud/xta/test/app/mapper/ResponseMapperTest.java b/src/test/java/de/ozgcloud/xta/test/app/mapper/ResponseMapperTest.java
index afa350ede993d9dcca8b76590d674e345bff7498..fee8821f41034c3b4506724114dfcecec86e94b7 100644
--- a/src/test/java/de/ozgcloud/xta/test/app/mapper/ResponseMapperTest.java
+++ b/src/test/java/de/ozgcloud/xta/test/app/mapper/ResponseMapperTest.java
@@ -1,7 +1,10 @@
 package de.ozgcloud.xta.test.app.mapper;
 
+import static de.ozgcloud.xta.test.app.factory.MessageMetaDataTestFactory.*;
+import static de.ozgcloud.xta.test.app.factory.PartyIdentifierTypeTestFactory.*;
+import static de.ozgcloud.xta.test.app.factory.XtaLookupServiceRequestTestFactory.*;
+import static de.ozgcloud.xta.test.app.factory.XtaMessageMetaDataTestFactory.*;
 import static de.ozgcloud.xta.test.app.mapper.ResponseMapper.*;
-import static de.ozgcloud.xta.test.app.service.XtaMessageMetaDataTestFactory.*;
 import static org.assertj.core.api.Assertions.*;
 
 import java.math.BigInteger;
@@ -14,11 +17,17 @@ import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mapstruct.factory.Mappers;
 
+import de.ozgcloud.xta.test.app.factory.XtaFileTestFactory;
+import de.ozgcloud.xta.test.app.factory.XtaLookupServiceRequestTestFactory;
+import de.ozgcloud.xta.test.app.factory.XtaMessageMetaDataTestFactory;
+import de.ozgcloud.xta.test.app.factory.XtaMessageTestFactory;
 import de.ozgcloud.xta.test.app.model.XtaFile;
 import de.ozgcloud.xta.test.app.model.XtaMessageMetaDataListing;
-import de.ozgcloud.xta.test.app.service.XtaMessageMetaDataTestFactory;
 import genv3.de.xoev.transport.xta.x211.ContentType;
+import genv3.de.xoev.transport.xta.x211.LookupServiceResponse;
+import genv3.de.xoev.transport.xta.x211.LookupServiceResultType;
 import genv3.eu.osci.ws.x2008.x05.transport.MsgStatusListType;
+import genv3.eu.osci.ws.x2014.x10.transport.DeliveryAttributesType;
 import genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData;
 import genv3.eu.osci.ws.x2014.x10.transport.QualifierType;
 import lombok.SneakyThrows;
@@ -273,6 +282,16 @@ public class ResponseMapperTest {
 					.isEqualTo(mapper.mapPartyIdentifierType(AUTHOR_IDENTIFIER));
 		}
 
+		@DisplayName("should set default sender identifier")
+		@Test
+		void shouldSetDefaultSenderIdentifier() {
+			var result = mapFirstMessageMetaData();
+
+			assertThat(result.getOriginators().getSender().getIdentifier())
+					.usingRecursiveComparison()
+					.isEqualTo(mapper.mapPartyIdentifierType(SENDER_IDENTIFIER));
+		}
+
 		@DisplayName("should map reader identifier")
 		@Test
 		void shouldMapReaderIdentifier() {
@@ -283,10 +302,46 @@ public class ResponseMapperTest {
 					.isEqualTo(mapper.mapPartyIdentifierType(READER_IDENTIFIER));
 		}
 
+		@DisplayName("should set default delivery attribute delivery")
+		@Test
+		void shouldSetDefaultDeliveryAttributeDelivery() {
+			var result = mapFirstMessageMetaDataDelivery();
+
+			assertThat(result.getDelivery()).isNotNull();
+		}
+
+		@DisplayName("should set default delivery attribute initial fetch")
+		@Test
+		void shouldSetDefaultDeliveryAttributeInitialFetch() {
+			var result = mapFirstMessageMetaDataDelivery();
+
+			assertThat(result.getInitialFetch()).isNotNull();
+		}
+
+		@DisplayName("should set default delivery attribute initial send")
+		@Test
+		void shouldSetDefaultDeliveryAttributeInitialSend() {
+			var result = mapFirstMessageMetaDataDelivery();
+
+			assertThat(result.getInitialSend()).isNotNull();
+		}
+
+		@DisplayName("should set default delivery attribute origin")
+		@Test
+		void shouldSetDefaultDeliveryAttributeOrigin() {
+			var result = mapFirstMessageMetaDataDelivery();
+
+			assertThat(result.getOrigin()).isNotNull();
+		}
+
 		private MsgStatusListType doMapping() {
 			return mapper.mapMsgStatusListType(xtaMessageMetaDataListing);
 		}
 
+		private DeliveryAttributesType mapFirstMessageMetaDataDelivery() {
+			return mapFirstMessageMetaData().getDeliveryAttributes();
+		}
+
 		private MessageMetaData mapFirstMessageMetaData() {
 			return doMapping().getMessageMetaData().getFirst();
 		}
@@ -357,4 +412,73 @@ public class ResponseMapperTest {
 			}
 		}
 	}
+
+	@DisplayName("map MsgBoxResponseType from requestId")
+	@Nested
+	class TestMapMsgBoxResponseTypeFromRequestId {
+
+		@DisplayName("should map message box response type from request id")
+		@Test
+		void shouldMapMsgBoxResponseTypeFromRequestId() {
+			var result = mapper.mapMsgBoxResponseTypeFromRequestId(REQUEST_ID);
+
+			assertThat(result.getMsgBoxRequestID()).isEqualTo(REQUEST_ID);
+		}
+
+		@DisplayName("should map items pending to zero")
+		@Test
+		void shouldMapItemsPendingToZero() {
+			var result = mapper.mapMsgBoxResponseTypeFromRequestId(REQUEST_ID);
+
+			assertThat(result.getItemsPending()).isEqualTo(BigInteger.ZERO);
+		}
+
+		@DisplayName("should set no messages available to null")
+		@Test
+		void shouldSetNoMessagesAvailableToNull() {
+			var result = mapper.mapMsgBoxResponseTypeFromRequestId(REQUEST_ID);
+
+			assertThat(result.getNoMessageAvailable()).isNull();
+		}
+	}
+
+	@DisplayName("map lookup service response")
+	@Nested
+	class TestMapLookupServiceResponse {
+
+		@DisplayName("should map service type")
+		@Test
+		void shouldMapServiceType() {
+			var result = getFirstLookupServiceResult();
+
+			assertThat(result.getServiceType()).isEqualTo(LOOKUP_SERVICE_SERVICE);
+		}
+
+		@DisplayName("should map reader identifier")
+		@Test
+		void shouldMapReaderIdentifier() {
+			var result = getFirstLookupServiceResult();
+
+			assertThat(result.getReader().getIdentifier())
+					.usingRecursiveComparison()
+					.isEqualTo(READER_PARTY_IDENTIFIER);
+		}
+
+		@DisplayName("should map service is available value")
+		@Test
+		void shouldMapServiceIsAvailableValue() {
+			var result = getFirstLookupServiceResult();
+
+			assertThat(result.getIsServiceAvailableValue().isServiceIsAvailable()).isTrue();
+		}
+
+		private LookupServiceResultType getFirstLookupServiceResult() {
+			return doMapping().getLookupServiceResultList().getLookupServiceResult().getFirst();
+		}
+
+		private LookupServiceResponse doMapping() {
+			return mapper.mapLookupServiceResponse(XtaLookupServiceRequestTestFactory.create());
+		}
+	}
+
 }
diff --git a/src/test/java/de/ozgcloud/xta/test/app/server/ManagementPortImplTest.java b/src/test/java/de/ozgcloud/xta/test/app/server/ManagementPortImplTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..65741330a0c51de32724284959fe827644b8bdce
--- /dev/null
+++ b/src/test/java/de/ozgcloud/xta/test/app/server/ManagementPortImplTest.java
@@ -0,0 +1,116 @@
+package de.ozgcloud.xta.test.app.server;
+
+import static de.ozgcloud.xta.test.app.factory.MessageMetaDataTestFactory.*;
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import org.apache.cxf.ws.addressing.AttributedURIType;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import de.ozgcloud.xta.test.app.mapper.RequestMapper;
+import de.ozgcloud.xta.test.app.mapper.ResponseMapper;
+import de.ozgcloud.xta.test.app.model.XtaLookupServiceRequest;
+import de.ozgcloud.xta.test.app.service.XtaMessageService;
+import de.ozgcloud.xta.test.app.validation.RequestValidator;
+import genv3.de.xoev.transport.xta.x211.LookupServiceRequest;
+import genv3.de.xoev.transport.xta.x211.LookupServiceResponse;
+import genv3.eu.osci.ws.x2014.x10.transport.PartyType;
+import lombok.SneakyThrows;
+
+public class ManagementPortImplTest {
+
+	@InjectMocks
+	private ManagementPortImpl managementPortImpl;
+
+	@Mock
+	private XtaMessageService xtaMessageService;
+	@Mock
+	private ResponseMapper responseMapper;
+	@Mock
+	private RequestMapper requestMapper;
+	@Mock
+	private RequestValidator requestValidator;
+
+	@DisplayName("create message id")
+	@Nested
+	class TestCreateMessageId {
+		@Mock
+		private PartyType authorIdentifier;
+
+		@Mock
+		private AttributedURIType createdMessageId;
+
+		@BeforeEach
+		void beforeEach() {
+			when(xtaMessageService.createMessageId()).thenReturn(MESSAGE_ID);
+			when(responseMapper.mapCreateMessageIdResponse(MESSAGE_ID)).thenReturn(createdMessageId);
+		}
+
+		@DisplayName("should return")
+		@Test
+		@SneakyThrows
+		void shouldCreateMessageId() {
+			var result = managementPortImpl.createMessageId(authorIdentifier);
+
+			assertThat(result).isEqualTo(createdMessageId);
+		}
+	}
+
+	@DisplayName("check account active")
+	@Nested
+	class TestCheckAccountActive {
+		@Mock
+		private PartyType authorIdentifier;
+
+		@DisplayName("should return")
+		@Test
+		@SneakyThrows
+		void shouldAcceptRequest() {
+			managementPortImpl.checkAccountActive(authorIdentifier);
+		}
+	}
+
+	@DisplayName("lookup service")
+	@Nested
+	class TestLookupService {
+		@Mock
+		private LookupServiceRequest lookupServiceRequest;
+		@Mock
+		private PartyType authorIdentifier;
+
+		@Mock
+		private XtaLookupServiceRequest request;
+
+		@Mock
+		private LookupServiceResponse response;
+
+		@BeforeEach
+		void beforeEach() {
+			when(requestMapper.mapXtaLookupServiceRequest(lookupServiceRequest, authorIdentifier)).thenReturn(request);
+			when(responseMapper.mapLookupServiceResponse(request)).thenReturn(response);
+		}
+
+		@DisplayName("should validate request")
+		@Test
+		@SneakyThrows
+		void shouldValidateRequest() {
+			managementPortImpl.lookupService(lookupServiceRequest, authorIdentifier);
+
+			verify(requestValidator).validate(request);
+		}
+
+		@DisplayName("should return")
+		@Test
+		@SneakyThrows
+		void shouldReturn() {
+			var result = managementPortImpl.lookupService(lookupServiceRequest, authorIdentifier);
+
+			assertThat(result).isEqualTo(response);
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/test/java/de/ozgcloud/xta/test/app/server/MsgBoxPortImplTest.java b/src/test/java/de/ozgcloud/xta/test/app/server/MsgBoxPortImplTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..0caf89774c2e0e9a35b69acc1517a8c57ef27b8e
--- /dev/null
+++ b/src/test/java/de/ozgcloud/xta/test/app/server/MsgBoxPortImplTest.java
@@ -0,0 +1,341 @@
+package de.ozgcloud.xta.test.app.server;
+
+import static de.ozgcloud.xta.test.app.factory.MessageMetaDataTestFactory.*;
+import static de.ozgcloud.xta.test.app.factory.XtaMessageMetaDataTestFactory.*;
+import static de.ozgcloud.xta.test.app.mapper.ResponseMapper.*;
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Optional;
+
+import jakarta.xml.ws.Holder;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import de.ozgcloud.xta.test.app.mapper.ExceptionMapper;
+import de.ozgcloud.xta.test.app.mapper.RequestMapper;
+import de.ozgcloud.xta.test.app.mapper.ResponseMapper;
+import de.ozgcloud.xta.test.app.model.XtaCloseRequest;
+import de.ozgcloud.xta.test.app.model.XtaGetMessageRequest;
+import de.ozgcloud.xta.test.app.model.XtaMessage;
+import de.ozgcloud.xta.test.app.model.XtaMessageMetaDataListing;
+import de.ozgcloud.xta.test.app.model.XtaMessageMetaDataListingRequest;
+import de.ozgcloud.xta.test.app.service.XtaMessageService;
+import de.ozgcloud.xta.test.app.validation.RequestValidator;
+import genv3.de.xoev.transport.xta.x211.GenericContentContainer;
+import genv3.de.xoev.transport.xta.x211.InvalidMessageIDException;
+import genv3.de.xoev.transport.xta.x211.XTAWSTechnicalProblemException;
+import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxCloseRequestType;
+import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxFetchRequest;
+import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxResponseType;
+import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxStatusListRequestType;
+import genv3.eu.osci.ws.x2008.x05.transport.MsgStatusListType;
+import genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData;
+import genv3.eu.osci.ws.x2014.x10.transport.PartyType;
+import lombok.SneakyThrows;
+
+public class MsgBoxPortImplTest {
+	@InjectMocks
+	private MsgBoxPortImpl msgBoxPortImpl;
+
+	@Mock
+	private RequestMapper requestMapper;
+
+	@Mock
+	private RequestValidator requestValidator;
+
+	@Mock
+	private ExceptionMapper exceptionMapper;
+
+	@Mock
+	private ResponseMapper responseMapper;
+
+	@Mock
+	private XtaMessageService xtaMessageService;
+
+	@DisplayName("get message")
+	@Nested
+	class TestGetMessage {
+		private static final String MESSAGE_ID = "message-id";
+
+		@Mock
+		private MsgBoxFetchRequest fetchRequest;
+		@Mock
+		private PartyType authorIdentifier;
+		@Mock
+		private XtaMessage xtaMessage;
+		@Mock
+		private GenericContentContainer mappedGenericContentContainer;
+		@Mock
+		private MessageMetaData mappedMessageMetaData;
+		@Mock
+		private MsgBoxResponseType mappedFetchResponseHeader;
+
+		private Holder<MessageMetaData> messageMetaDataHolder;
+		private Holder<MsgBoxResponseType> responseHeaderHolder;
+		private XtaGetMessageRequest request;
+
+		@BeforeEach
+		void mock() {
+			request = XtaGetMessageRequest.builder()
+					.messageId(MESSAGE_ID)
+					.clientIdentifier(READER_IDENTIFIER)
+					.build();
+
+			messageMetaDataHolder = new Holder<>();
+			responseHeaderHolder = new Holder<>();
+			when(requestMapper.mapXtaGetMessageRequest(fetchRequest, authorIdentifier)).thenReturn(request);
+		}
+
+		@DisplayName("with valid request")
+		@Nested
+		class TestWithValidRequest {
+
+			@BeforeEach
+			void setup() {
+				when(xtaMessageService.getMessage(request)).thenReturn(Optional.of(xtaMessage));
+
+				when(responseMapper.mapMessageMetaData(xtaMessage.metaData())).thenReturn(mappedMessageMetaData);
+				when(xtaMessageService.createRequestId()).thenReturn(REQUEST_ID);
+				when(responseMapper.mapMsgBoxResponseTypeFromRequestId(REQUEST_ID)).thenReturn(mappedFetchResponseHeader);
+				when(responseMapper.mapGenericContentContainerFromXtaMessage(xtaMessage)).thenReturn(mappedGenericContentContainer);
+			}
+
+			@DisplayName("should assign message meta data")
+			@Test
+			void shouldAssignMessageMetaData() {
+				getMessage();
+
+				assertThat(messageMetaDataHolder.value).isEqualTo(mappedMessageMetaData);
+			}
+
+			@DisplayName("should assign fetch response header")
+			@Test
+			void shouldAssignFetchResponseHeader() {
+				getMessage();
+
+				assertThat(responseHeaderHolder.value).isEqualTo(mappedFetchResponseHeader);
+			}
+
+			@DisplayName("should return")
+			@Test
+			void shouldReturn() {
+				var genericContentContainer = getMessage();
+
+				assertThat(genericContentContainer).isEqualTo(mappedGenericContentContainer);
+			}
+		}
+
+		@DisplayName("with invalid message id")
+		@Nested
+		class TestWithInvalidMessageId {
+
+			@Mock
+			private InvalidMessageIDException exception;
+
+			@DisplayName("should throw exception")
+			@Test
+			void shouldThrowException() {
+				when(xtaMessageService.getMessage(request)).thenReturn(Optional.empty());
+				when(exceptionMapper.createInvalidMessageIDException(any())).thenReturn(exception);
+
+				assertThatThrownBy(TestGetMessage.this::getMessage)
+						.isEqualTo(exception);
+			}
+		}
+
+		@DisplayName("with invalid request")
+		@Nested
+		class TestWithInvalidRequest {
+
+			@BeforeEach
+			@SneakyThrows
+			void setup() {
+				doThrow(new XTAWSTechnicalProblemException()).when(requestValidator).validate(request);
+			}
+
+			@DisplayName("should throw exception")
+			@Test
+			void shouldThrowException() {
+				assertThatThrownBy(TestGetMessage.this::getMessage)
+						.isInstanceOf(XTAWSTechnicalProblemException.class);
+			}
+		}
+
+		@SneakyThrows
+		private GenericContentContainer getMessage() {
+			return msgBoxPortImpl.getMessage(fetchRequest, authorIdentifier, messageMetaDataHolder, responseHeaderHolder);
+		}
+	}
+
+	@DisplayName("get status list")
+	@Nested
+	class TestGetStatusList {
+		@Mock
+		private MsgBoxStatusListRequestType statusListRequest;
+
+		@Mock
+		private PartyType authorIdentifier;
+
+		private Holder<MsgBoxResponseType> msgBoxResponseHeader;
+
+		@Mock
+		private XtaMessageMetaDataListingRequest request;
+
+		@BeforeEach
+		void mock() {
+			when(requestMapper.mapMessageMetaDataListingRequest(statusListRequest, authorIdentifier)).thenReturn(request);
+
+			msgBoxResponseHeader = new Holder<>();
+		}
+
+		@DisplayName("with valid request")
+		@Nested
+		class TestWithValidRequest {
+			@Mock
+			private XtaMessageMetaDataListing listing;
+			@Mock
+			private MsgStatusListType statusListType;
+			@Mock
+			private MsgBoxResponseType mappedMsgBoxResponseHeader;
+
+			@BeforeEach
+			void setup() {
+				when(xtaMessageService.getStatusList(request)).thenReturn(listing);
+				when(responseMapper.mapMsgStatusListType(listing)).thenReturn(statusListType);
+				when(responseMapper.mapMsgBoxResponseType(listing)).thenReturn(mappedMsgBoxResponseHeader);
+			}
+
+			@DisplayName("should return")
+			@Test
+			void shouldReturn() {
+				var msgStatusList = getStatusList();
+
+				assertThat(msgStatusList).isEqualTo(statusListType);
+			}
+
+			@DisplayName("should assign header")
+			@Test
+			void shouldAssignHeader() {
+				getStatusList();
+
+				assertThat(msgBoxResponseHeader.value).isEqualTo(mappedMsgBoxResponseHeader);
+			}
+		}
+
+		@DisplayName("with invalid request")
+		@Nested
+		class TestWithInvalidRequest {
+
+			@BeforeEach
+			@SneakyThrows
+			void setup() {
+				doThrow(new XTAWSTechnicalProblemException()).when(requestValidator).validate(request);
+			}
+
+			@DisplayName("should throw exception")
+			@Test
+			void shouldThrowException() {
+				assertThatThrownBy(TestGetStatusList.this::getStatusList)
+						.isInstanceOf(XTAWSTechnicalProblemException.class);
+			}
+		}
+
+		@SneakyThrows
+		private MsgStatusListType getStatusList() {
+			return msgBoxPortImpl.getStatusList(statusListRequest, authorIdentifier, msgBoxResponseHeader);
+		}
+
+	}
+
+	@DisplayName("close")
+	@Nested
+	class TestClose {
+		@Mock
+		private MsgBoxCloseRequestType closeRequest;
+		@Mock
+		private PartyType authorIdentifier;
+
+		private XtaCloseRequest request;
+
+		@BeforeEach
+		void mock() {
+			request = XtaCloseRequest.builder()
+					.messageId(MESSAGE_ID)
+					.clientIdentifier(READER_IDENTIFIER)
+					.build();
+			when(requestMapper.mapXtaCloseRequest(closeRequest, authorIdentifier)).thenReturn(request);
+		}
+
+		@DisplayName("with valid request")
+		@Nested
+		class TestWithValidRequest {
+			@BeforeEach
+			void setup() {
+				when(xtaMessageService.closeMessage(request)).thenReturn(true);
+			}
+
+			@DisplayName("should call close message")
+			@Test
+			@SneakyThrows
+			void shouldCallCloseMessage() {
+				close();
+
+				verify(xtaMessageService).closeMessage(any());
+			}
+
+			@DisplayName("should return")
+			@Test
+			void shouldReturn() {
+				close();
+			}
+		}
+
+		@DisplayName("with invalid message id")
+		@Nested
+		class TestWithInvalidMessageId {
+
+			@Mock
+			private InvalidMessageIDException exception;
+
+			@DisplayName("should throw exception")
+			@Test
+			void shouldThrowException() {
+				when(xtaMessageService.closeMessage(request)).thenReturn(false);
+				when(exceptionMapper.createInvalidMessageIDException(any())).thenReturn(exception);
+
+				assertThatThrownBy(TestClose.this::close)
+						.isEqualTo(exception);
+			}
+		}
+
+		@DisplayName("with invalid request")
+		@Nested
+		class TestWithInvalidRequest {
+			@BeforeEach
+			@SneakyThrows
+			void setup() {
+				doThrow(new XTAWSTechnicalProblemException()).when(requestValidator).validate(any());
+			}
+
+			@DisplayName("should throw exception")
+			@Test
+			void shouldThrowException() {
+				assertThatThrownBy(TestClose.this::close)
+						.isInstanceOf(XTAWSTechnicalProblemException.class);
+			}
+		}
+
+		@SneakyThrows
+		private void close() {
+			msgBoxPortImpl.close(closeRequest, authorIdentifier);
+		}
+	}
+
+}
diff --git a/src/test/java/de/ozgcloud/xta/test/app/server/SendXtaPortImplTest.java b/src/test/java/de/ozgcloud/xta/test/app/server/SendXtaPortImplTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..b78c3390cd754d26471e27cb76a9eef2ab001939
--- /dev/null
+++ b/src/test/java/de/ozgcloud/xta/test/app/server/SendXtaPortImplTest.java
@@ -0,0 +1,100 @@
+package de.ozgcloud.xta.test.app.server;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.ozgcloud.xta.test.app.mapper.ExceptionMapper;
+import de.ozgcloud.xta.test.app.mapper.RequestMapper;
+import de.ozgcloud.xta.test.app.model.XtaMessage;
+import de.ozgcloud.xta.test.app.service.XtaMessageService;
+import de.ozgcloud.xta.test.app.validation.RequestValidator;
+import genv3.de.xoev.transport.xta.x211.GenericContentContainer;
+import genv3.de.xoev.transport.xta.x211.ParameterIsNotValidException;
+import genv3.de.xoev.transport.xta.x211.XTAWSTechnicalProblemException;
+import genv3.eu.osci.ws.x2008.x05.transport.X509TokenContainerType;
+import genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData;
+import lombok.SneakyThrows;
+
+public class SendXtaPortImplTest {
+	@Spy
+	@InjectMocks
+	private SendXtaPortImpl sendXtaPortImpl;
+	@Mock
+	private RequestValidator requestValidator;
+	@Mock
+	private RequestMapper requestMapper;
+	@Mock
+	private XtaMessageService xtaMessageService;
+	@Mock
+	private ExceptionMapper exceptionMapper;
+
+	@DisplayName("send message")
+	@Nested
+	class TestSendMessage {
+		@Mock
+		private GenericContentContainer genericContainer;
+		@Mock
+		private MessageMetaData messageMetaData;
+		@Mock
+		private X509TokenContainerType x509TokenContainer;
+
+		private ParameterIsNotValidException parameterIsNotValidException;
+
+		private XTAWSTechnicalProblemException technicalProblemException;
+
+		@Mock
+		private XtaMessage xtaMessage;
+
+		@BeforeEach
+		void mock() {
+			parameterIsNotValidException = new ParameterIsNotValidException();
+			technicalProblemException = new XTAWSTechnicalProblemException();
+			when(requestMapper.mapXtaMessageFromGenericContentContainer(genericContainer, messageMetaData)).thenReturn(xtaMessage);
+		}
+
+		@DisplayName("should return")
+		@Test
+		@SneakyThrows
+		void shouldSendMessage() {
+			when(xtaMessageService.sendMessage(xtaMessage)).thenReturn(true);
+
+			sendMessage();
+		}
+
+		@DisplayName("should throw if send fails")
+		@Test
+		void shouldThrowIfSendFails() {
+			when(xtaMessageService.sendMessage(xtaMessage)).thenReturn(false);
+			when(exceptionMapper.createParameterIsNotValidException(any())).thenReturn(parameterIsNotValidException);
+
+			assertThatThrownBy(this::sendMessage)
+					.isEqualTo(parameterIsNotValidException);
+		}
+
+		@DisplayName("should validate request")
+		@Test
+		@SneakyThrows
+		void shouldValidateRequest() {
+			doThrow(technicalProblemException).when(requestValidator).validate(xtaMessage);
+
+			assertThatThrownBy(this::sendMessage)
+					.isEqualTo(technicalProblemException);
+		}
+
+		@SneakyThrows
+		private void sendMessage() {
+			sendXtaPortImpl.sendMessage(genericContainer, messageMetaData, x509TokenContainer);
+		}
+
+	}
+
+}
diff --git a/src/test/java/de/ozgcloud/xta/test/app/service/XtaMessageServiceTest.java b/src/test/java/de/ozgcloud/xta/test/app/service/XtaMessageServiceTest.java
index 08fecc6dfedf7dc21599285b9f51c0fa5e85c833..6723c0e40c5cb749249d82aa4f8062f4e82511ba 100644
--- a/src/test/java/de/ozgcloud/xta/test/app/service/XtaMessageServiceTest.java
+++ b/src/test/java/de/ozgcloud/xta/test/app/service/XtaMessageServiceTest.java
@@ -1,22 +1,31 @@
 package de.ozgcloud.xta.test.app.service;
 
-import static de.ozgcloud.xta.test.app.mapper.XtaMessageTestFactory.*;
-import static de.ozgcloud.xta.test.app.service.XtaMessageMetaDataTestFactory.*;
+import static de.ozgcloud.xta.test.app.factory.XtaMessageMetaDataTestFactory.*;
+import static de.ozgcloud.xta.test.app.factory.XtaMessageTestFactory.*;
+import static de.ozgcloud.xta.test.app.validation.ValidXtaId.*;
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
 
 import java.math.BigInteger;
 import java.util.List;
 import java.util.Optional;
+import java.util.function.Predicate;
 
 import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.core.env.Environment;
 
 import de.ozgcloud.xta.test.app.data.XtaMessageRepository;
-import de.ozgcloud.xta.test.app.mapper.XtaMessageTestFactory;
+import de.ozgcloud.xta.test.app.factory.XtaCloseRequestTestFactory;
+import de.ozgcloud.xta.test.app.factory.XtaMessageTestFactory;
+import de.ozgcloud.xta.test.app.model.XtaGetMessageRequest;
 import de.ozgcloud.xta.test.app.model.XtaMessage;
 import de.ozgcloud.xta.test.app.model.XtaMessageMetaDataListing;
 import de.ozgcloud.xta.test.app.model.XtaMessageMetaDataListingRequest;
@@ -24,11 +33,15 @@ import de.ozgcloud.xta.test.app.model.XtaMessageMetaDataListingRequest;
 public class XtaMessageServiceTest {
 	@Mock
 	private XtaMessageRepository messageRepository;
+	@Mock
+	private Environment environment;
+
+	@Spy
 	@InjectMocks
 	private XtaMessageService service;
 
 	@Nested
-	class SendMessage {
+	class TestSendMessage {
 		public static final String MESSAGE_ID = "send_1";
 		private XtaMessage message;
 
@@ -48,13 +61,13 @@ public class XtaMessageServiceTest {
 	}
 
 	@Nested
-	class GetStatusList {
+	class TestGetStatusList {
 
-		private final int MAX_LIST_ITEMS = 50;
-		private final int MESSAGE_COUNT = 2;
+		private static final int MAX_LIST_ITEMS = 50;
+		private static final int MESSAGE_COUNT = 2;
 
 		private final XtaMessageMetaDataListingRequest messageMetaDataListingRequest = XtaMessageMetaDataListingRequest.builder()
-				.clientIdentifierValue(READER_IDENTIFIER.value())
+				.clientIdentifier(READER_IDENTIFIER)
 				.maxListItems(MAX_LIST_ITEMS)
 				.build();
 
@@ -66,7 +79,8 @@ public class XtaMessageServiceTest {
 			message1 = XtaMessageTestFactory.create(MESSAGE_ID_1);
 			message2 = XtaMessageTestFactory.create(MESSAGE_ID_2);
 
-			when(messageRepository.findByReaderIdentifierValueLimitedTo(READER_IDENTIFIER.value(), MAX_LIST_ITEMS)).thenReturn(List.of(message1, message2));
+			when(messageRepository.findByReaderIdentifierValueLimitedTo(READER_IDENTIFIER.value(), MAX_LIST_ITEMS)).thenReturn(
+					List.of(message1, message2));
 			when(messageRepository.countByReaderIdentifierValue(READER_IDENTIFIER.value())).thenReturn(BigInteger.valueOf(MESSAGE_COUNT));
 		}
 
@@ -90,34 +104,153 @@ public class XtaMessageServiceTest {
 
 	}
 
+	@DisplayName("get message")
 	@Nested
-	class GetMessage {
-		public static final String MESSAGE_ID = "get_1";
+	class TestGetMessage {
+		private static final XtaGetMessageRequest GET_MESSAGE_REQUEST = XtaGetMessageRequest.builder()
+				.messageId(MESSAGE_ID_1)
+				.clientIdentifier(READER_IDENTIFIER)
+				.build();
+		private static final Predicate<XtaMessage> IS_AUTHOR_OR_READER = m -> true;
+		private static final Predicate<XtaMessage> IS_NOT_AUTHOR_OR_READER = m -> false;
+
+		@Mock
 		private XtaMessage message;
 
-		@BeforeEach
-		void beforeEach() {
-			message = XtaMessageTestFactory.create(MESSAGE_ID);
-			when(messageRepository.get(MESSAGE_ID)).thenReturn(Optional.of(message));
+		@DisplayName("should return")
+		@Test
+		void shouldReturn() {
+			when(messageRepository.get(MESSAGE_ID_1)).thenReturn(Optional.of(message));
+			doReturn(IS_AUTHOR_OR_READER).when(service).isAuthorOrReaderOfMessage(READER_IDENTIFIER.value());
+
+			var result = service.getMessage(GET_MESSAGE_REQUEST);
+
+			assertThat(result).contains(message);
+		}
+
+		@DisplayName("should return empty if message id not found")
+		@Test
+		void shouldReturnEmptyIfMessageIdNotFound() {
+			when(messageRepository.get(MESSAGE_ID_1)).thenReturn(Optional.empty());
+
+			var result = service.getMessage(GET_MESSAGE_REQUEST);
+
+			assertThat(result).isEmpty();
+		}
+
+		@DisplayName("should return empty if not author or reader")
+		@Test
+		void shouldReturnEmptyIfNotAuthorOrReader() {
+			when(messageRepository.get(MESSAGE_ID_1)).thenReturn(Optional.of(message));
+			doReturn(IS_NOT_AUTHOR_OR_READER).when(service).isAuthorOrReaderOfMessage(READER_IDENTIFIER.value());
+
+			var result = service.getMessage(GET_MESSAGE_REQUEST);
+
+			assertThat(result).isEmpty();
+		}
+	}
+
+	@DisplayName("is author or reader of message")
+	@Nested
+	class TestIsAuthorOrReaderOfMessage {
+
+		@DisplayName("should return true if reader identifier value matches")
+		@Test
+		void shouldReturnTrueIfReaderIdentifierValueMatches() {
+			var message = XtaMessageTestFactory.create(MESSAGE_ID_1);
+
+			var result = service.isAuthorOrReaderOfMessage(READER_IDENTIFIER.value()).test(message);
+
+			assertThat(result).isTrue();
+		}
+
+		@DisplayName("should return true if author identifier value matches")
+		@Test
+		void shouldReturnTrueIfAuthorIdentifierValueMatches() {
+			var message = XtaMessageTestFactory.create(MESSAGE_ID_1);
+
+			var result = service.isAuthorOrReaderOfMessage(AUTHOR_IDENTIFIER.value()).test(message);
+
+			assertThat(result).isTrue();
+		}
+
+		@DisplayName("should return false if neither reader nor author identifier value matches")
+		@Test
+		void shouldReturnFalseIfNeitherReaderNorAuthorIdentifierValueMatches() {
+			var message = XtaMessageTestFactory.create(MESSAGE_ID_1);
+
+			var result = service.isAuthorOrReaderOfMessage("unknown").test(message);
+
+			assertThat(result).isFalse();
+		}
+	}
+
+	@DisplayName("close message")
+	@Nested
+	class TestCloseMessage {
+
+		@DisplayName("should return")
+		@ParameterizedTest
+		@ValueSource(booleans = { true, false })
+		void shouldReturn(boolean deleted) {
+			var request = XtaCloseRequestTestFactory.create();
+			when(messageRepository.deleteByMessageIdAndReaderIdentifierValue(
+					request.messageId(), request.clientIdentifier().value())
+			).thenReturn(deleted);
+
+			boolean result = service.closeMessage(request);
+
+			assertThat(result).isEqualTo(deleted);
+
 		}
+	}
+
+	@DisplayName("create message id")
+	@Nested
+	class TestCreateMessageId {
 
+		@DisplayName("should return unique id")
 		@Test
-		void shouldGetMessage() {
-			Optional<XtaMessage> result = service.getMessage(MESSAGE_ID);
+		void shouldReturnUniqueId() {
+			var result1 = service.createMessageId();
+			var result2 = service.createMessageId();
 
-			assertThat(result).contains(this.message);
+			assertThat(result1).isNotEqualTo(result2);
+		}
+
+		@DisplayName("should return")
+		@Test
+		void shouldReturn() {
+			when(environment.getProperty("spring.application.name")).thenReturn("app");
+
+			var result = service.createMessageId();
+
+			assertThat(result).startsWith("urn:" + MESSAGE_ID_NAMESPACE + ":app:");
 		}
 	}
 
+	@DisplayName("create request id")
 	@Nested
-	class CloseMessage {
-		public static final String MESSAGE_ID = "close_1";
+	class TestCreateRequestId {
 
+		@DisplayName("should return unique id")
 		@Test
-		void shouldCloseMessage() {
-			service.closeMessage(MESSAGE_ID);
+		void shouldReturnUniqueId() {
+			var result1 = service.createRequestId();
+			var result2 = service.createRequestId();
 
-			verify(messageRepository).delete(MESSAGE_ID);
+			assertThat(result1).isNotEqualTo(result2);
+		}
+
+		@DisplayName("should return")
+		@Test
+		void shouldReturn() {
+			when(environment.getProperty("spring.application.name")).thenReturn("app");
+
+			var result = service.createRequestId();
+
+			assertThat(result).startsWith("urn:" + REQUEST_ID_NAMESPACE + ":app:");
 		}
 	}
+
 }
diff --git a/src/test/java/de/ozgcloud/xta/test/app/util/XtaIdGeneratorTest.java b/src/test/java/de/ozgcloud/xta/test/app/util/XtaIdGeneratorTest.java
deleted file mode 100644
index 6f53c2c03dbd4e0d32b8ccb940fc1236bebefca7..0000000000000000000000000000000000000000
--- a/src/test/java/de/ozgcloud/xta/test/app/util/XtaIdGeneratorTest.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package de.ozgcloud.xta.test.app.util;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-import org.junit.jupiter.api.Test;
-
-public class XtaIdGeneratorTest {
-
-	@Test
-	void generateTest() {
-		// when
-		XtaId xtaMessageId1 = XtaIdGenerator.generateMessageId();
-		XtaId xtaMessageId2 = XtaIdGenerator.generateMessageId();
-
-		// then
-		assertNotNull(xtaMessageId1);
-		assertNotNull(xtaMessageId2);
-		assertEquals(xtaMessageId1.getSchema(), xtaMessageId2.getSchema());
-		assertEquals(xtaMessageId1.getNamespace(), xtaMessageId2.getNamespace());
-		assertEquals(xtaMessageId1.getApplication(), xtaMessageId2.getApplication());
-		assertNotEquals(xtaMessageId1.getUuid(), xtaMessageId2.getUuid());
-	}
-}
diff --git a/src/test/java/de/ozgcloud/xta/test/app/util/XtaIdTest.java b/src/test/java/de/ozgcloud/xta/test/app/util/XtaIdTest.java
deleted file mode 100644
index 6417b1f7f60c785ed6e9fbd9a781f47ab397198a..0000000000000000000000000000000000000000
--- a/src/test/java/de/ozgcloud/xta/test/app/util/XtaIdTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package de.ozgcloud.xta.test.app.util;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.util.Optional;
-
-import org.junit.jupiter.api.Test;
-
-public class XtaIdTest {
-
-	@Test
-	void parseTest_messageIdIsCorrect_returnedOptionalIsPresent() {
-		// given
-		String messageId = "urn:de:xta:messageid:application:000ca2fe-f4e1-45c2-8233-3a0eb760bd16";
-
-		// when
-		Optional<XtaId> optId = XtaId.parse(messageId);
-
-		// then
-		assertTrue(optId.isPresent());
-		XtaId xtaMessageId = optId.get();
-		assertAll(
-				() -> assertEquals("urn", xtaMessageId.getSchema(), "wrong schema"),
-				() -> assertEquals("de:xta:messageid", xtaMessageId.getNamespace(), "wrong namespace"),
-				() -> assertEquals("application", xtaMessageId.getApplication(), "wrong application"),
-				() -> assertEquals("000ca2fe-f4e1-45c2-8233-3a0eb760bd16", xtaMessageId.getUuid(), "wrong uuid"));
-	}
-
-	@Test
-	void parseTest_messageIdIsNotCorrect_returnedOptionalIsEmpty() {
-		// given
-		String messageId = "urn:application:000ca2fe-f4e1-45c2-8233-3a0eb760bd16";
-
-		// when
-		Optional<XtaId> optId = XtaId.parse(messageId);
-
-		// then
-		assertTrue(optId.isEmpty());
-	}
-}
diff --git a/src/test/java/de/ozgcloud/xta/test/app/validation/RequestValidatorTest.java b/src/test/java/de/ozgcloud/xta/test/app/validation/RequestValidatorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..d326d6de4269ea1fac00784f62b16f4c21e511f4
--- /dev/null
+++ b/src/test/java/de/ozgcloud/xta/test/app/validation/RequestValidatorTest.java
@@ -0,0 +1,97 @@
+package de.ozgcloud.xta.test.app.validation;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import de.ozgcloud.xta.test.app.factory.XtaGetMessageRequestTestFactory;
+import de.ozgcloud.xta.test.app.mapper.ExceptionMapper;
+import de.ozgcloud.xta.test.app.model.XtaIdentifier;
+import genv3.de.xoev.transport.xta.x211.XTAWSTechnicalProblemException;
+import lombok.SneakyThrows;
+
+class RequestValidatorTest {
+
+	@InjectMocks
+	private RequestValidator validator;
+
+	@Mock
+	private ExceptionMapper exceptionMapper;
+
+	@Mock
+	private XTAWSTechnicalProblemException exception;
+
+	@DisplayName("validate xta get message request")
+	@Nested
+	class TestValidateXtaGetMessageRequest {
+
+		@DisplayName("should return")
+		@Test
+		@SneakyThrows
+		void shouldReturn() {
+			validator.validate(XtaGetMessageRequestTestFactory.createBuilder()
+					.clientIdentifier(XtaIdentifier.builder()
+							.value("not blank")
+							.build())
+					.build());
+		}
+
+		@DisplayName("should throw if null")
+		@Test
+		void shouldThrowIfNull() {
+			when(exceptionMapper.createTechnicalProblemException(any())).thenReturn(exception);
+
+			assertThatThrownBy(() -> validator.validate(null)).isEqualTo(exception);
+		}
+
+		@DisplayName("with invalid request")
+		@Nested
+		class TestWithInvalidRequest {
+
+			@BeforeEach
+			void mock() {
+				when(exceptionMapper.createTechnicalProblemException(any())).thenReturn(exception);
+			}
+
+			@DisplayName("should throw if message id is null")
+			@Test
+			void shouldThrowIfMessageIdIsNull() {
+				var request = XtaGetMessageRequestTestFactory.createBuilder()
+						.messageId(null)
+						.build();
+
+				assertThatThrownBy(() -> validator.validate(request)).isEqualTo(exception);
+			}
+
+			@DisplayName("should throw if message id does not match pattern")
+			@Test
+			void shouldThrowIfMessageIdDoesNotMatchPattern() {
+				var request = XtaGetMessageRequestTestFactory.createBuilder()
+						.messageId("urn:unknown-namespace:application:000ca2fe-f4e1-45c2-8233-3a0eb760bd16")
+						.build();
+
+				assertThatThrownBy(() -> validator.validate(request)).isEqualTo(exception);
+			}
+
+			@DisplayName("should throw if clientIdentifier value is null")
+			@Test
+			void shouldThrowIfClientIdentifierValueIsNull() {
+				var request = XtaGetMessageRequestTestFactory.createBuilder()
+						.clientIdentifier(XtaIdentifier.builder()
+								.value(null)
+								.build())
+						.build();
+
+				assertThatThrownBy(() -> validator.validate(request)).isEqualTo(exception);
+			}
+		}
+
+	}
+
+}
\ No newline at end of file
diff --git a/src/test/resources/configDefaultTest.yaml b/src/test/resources/configDefaultTest.yaml
deleted file mode 100644
index 948caf8ebe703e4f83dd3265040582508472eb6f..0000000000000000000000000000000000000000
--- a/src/test/resources/configDefaultTest.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-protocolMetadata:
-  softwareManufacturer: "Nortal AG"
-  softwareName: "Dummy Produkt"
-  softwareVersion: "1.0.0"
-  street: "Knesebeckstraße"
-  streetNo: "1"
-  zipCode: "10623"
-  city: "Berlin"
-  addressAddition: null
-clientProperties:
-  serverUrl:
-    managementPort: "https://localhost:9443/services/XTAService/ManagementPort"
-    sendPort: "https://localhost:9443/services/XTAService/MsgBoxPort"
-    msgBoxPort: "https://localhost:9443/services/XTAService/SendXtaPort"
-  checkHostnameInCertificate: true
-  keyStore: "classpath:store/john_smith_xta_tester.p12"
-  keyStorePassword: "password"
-  keyPassword: "password"
-  keyAlias: null
-  trustStore: "classpath:store/xta-test-server_truststore.jks"
-  trustStorePassword: "password"