From 510ad7a281ca75ba5746bdf18f1094a3ece3337a Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Mon, 9 Sep 2024 18:00:05 +0200
Subject: [PATCH] KOP-2149 sendMessage: Implement sending and support undefined
 businessScenarios

---
 .../de/ozgcloud/xta/client/XtaClient.java     | 30 +++++++
 .../xta/client/mapper/RequestMapper.java      | 58 ++++++++-----
 .../xta/client/mapper/ResponseMapper.java     |  2 +
 .../xta/client/model/XtaMessageMetaData.java  |  5 +-
 .../xta/client/XtaClientManualITCase.java     | 23 +++++
 .../de/ozgcloud/xta/client/XtaClientTest.java | 84 +++++++++++++++++++
 .../xta/client/XtaMessageExampleLoader.java   |  6 +-
 .../xta/client/core/RequestMapperTest.java    | 28 +++++++
 .../xta/client/core/ResponseMapperTest.java   | 16 ++++
 .../factory/MessageMetaDataTestFactory.java   |  2 +
 .../XtaMessageMetaDataTestFactory.java        |  2 +
 .../messages/dfoerdermittel/xta-message.yaml  |  2 +
 .../versammlungsanzeige/xta-message.yaml      |  2 +
 13 files changed, 237 insertions(+), 23 deletions(-)

diff --git a/src/main/java/de/ozgcloud/xta/client/XtaClient.java b/src/main/java/de/ozgcloud/xta/client/XtaClient.java
index 039964a..a22c002 100644
--- a/src/main/java/de/ozgcloud/xta/client/XtaClient.java
+++ b/src/main/java/de/ozgcloud/xta/client/XtaClient.java
@@ -1,14 +1,21 @@
 package de.ozgcloud.xta.client;
 
+import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotBlank;
 
 import de.ozgcloud.xta.client.config.XtaClientConfig;
 import de.ozgcloud.xta.client.core.WrappedXtaService;
 import de.ozgcloud.xta.client.model.XtaIdentifier;
+import de.ozgcloud.xta.client.model.XtaMessage;
 import de.ozgcloud.xta.client.model.XtaMessageAndTransportReport;
 import de.ozgcloud.xta.client.model.XtaMessageMetaDataListing;
+import de.ozgcloud.xta.client.model.XtaTransportReport;
 import genv3.de.xoev.transport.xta.x211.InvalidMessageIDException;
+import genv3.de.xoev.transport.xta.x211.MessageSchemaViolationException;
+import genv3.de.xoev.transport.xta.x211.MessageVirusDetectionException;
+import genv3.de.xoev.transport.xta.x211.ParameterIsNotValidException;
 import genv3.de.xoev.transport.xta.x211.PermissionDeniedException;
+import genv3.de.xoev.transport.xta.x211.SyncAsyncException;
 import genv3.de.xoev.transport.xta.x211.XTAWSTechnicalProblemException;
 import lombok.AccessLevel;
 import lombok.Builder;
@@ -74,6 +81,29 @@ public class XtaClient {
 				.build();
 	}
 
+	public XtaTransportReport sendMessage(@Valid XtaMessage messageWithoutMessageId)
+			throws XTAWSTechnicalProblemException, PermissionDeniedException, InvalidMessageIDException, SyncAsyncException,
+			MessageVirusDetectionException, MessageSchemaViolationException, ParameterIsNotValidException {
+
+		var metaData = messageWithoutMessageId.metaData();
+		var authorIdentifier = metaData.authorIdentifier();
+		service.checkAccountActive(authorIdentifier);
+		service.lookupService(metaData.service(), metaData.readerIdentifier(), authorIdentifier);
+
+		var messageId = service.createMessageId(authorIdentifier);
+		service.sendMessage(createXtaMessageWithMessageId(messageWithoutMessageId, messageId));
+
+		return service.getTransportReport(messageId, authorIdentifier);
+	}
+
+	XtaMessage createXtaMessageWithMessageId(XtaMessage messageWithoutMessageId, String messageId) {
+		return messageWithoutMessageId.toBuilder()
+				.metaData(messageWithoutMessageId.metaData().toBuilder()
+						.messageId(messageId)
+						.build())
+				.build();
+	}
+
 	XtaIdentifier deriveIdentifier(String xtaIdentifier) {
 		return config.getClientIdentifiers().stream()
 				.filter(id -> id.value().equals(xtaIdentifier))
diff --git a/src/main/java/de/ozgcloud/xta/client/mapper/RequestMapper.java b/src/main/java/de/ozgcloud/xta/client/mapper/RequestMapper.java
index dbcefae..f2fbed4 100644
--- a/src/main/java/de/ozgcloud/xta/client/mapper/RequestMapper.java
+++ b/src/main/java/de/ozgcloud/xta/client/mapper/RequestMapper.java
@@ -3,10 +3,11 @@ package de.ozgcloud.xta.client.mapper;
 import org.apache.cxf.ws.addressing.AttributedURIType;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
+import org.mapstruct.Named;
 import org.mapstruct.ReportingPolicy;
 
-import de.ozgcloud.xta.client.model.XtaIdentifier;
 import de.ozgcloud.xta.client.model.XtaFile;
+import de.ozgcloud.xta.client.model.XtaIdentifier;
 import de.ozgcloud.xta.client.model.XtaMessage;
 import de.ozgcloud.xta.client.model.XtaMessageMetaData;
 import genv3.de.xoev.transport.xta.x211.ContentType;
@@ -16,6 +17,7 @@ import genv3.de.xoev.transport.xta.x211.LookupServiceType;
 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.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.PartyType;
@@ -25,11 +27,8 @@ import genv3.eu.osci.ws.x2014.x10.transport.QualifierType;
 		unmappedTargetPolicy = ReportingPolicy.ERROR
 )
 public interface RequestMapper {
-
-	String BUSINESS_SCENARIO_LIST_URI = "urn:de:dataport:codeliste:business.scenario";
 	String MESSAGE_TYPE_LIST_URI = "urn:de:payloadSchema:elementName";
 	String MESSAGE_TYPE_LIST_VERSION_ID = "1.0";
-	String BUSINESS_SCENARIO_LIST_VERSION_ID = "1";
 	String IDENTIFIER_TYPE = "xoev";
 	String CLOSE_REQUEST_ID = "1";
 
@@ -44,9 +43,7 @@ public interface RequestMapper {
 	@Mapping(target = "msgSelector", ignore = true)
 	MsgBoxStatusListRequestType mapMsgBoxStatusListRequestTypeFromMaxListItems(Integer maxListItems);
 
-	@Mapping(target = "qualifier.service", source = "service")
-	@Mapping(target = "qualifier.businessScenario", source = "businessScenarioCode")
-	@Mapping(target = "qualifier.messageType", source = ".")
+	@Mapping(target = "qualifier", source = ".")
 	@Mapping(target = "msgIdentification.messageID.value", source = "messageId")
 	@Mapping(target = "originators.author.identifier", source = "authorIdentifier")
 	@Mapping(target = "destinations.reader.identifier", source = "readerIdentifier")
@@ -56,19 +53,6 @@ public interface RequestMapper {
 	@Mapping(target = "messageProperties", ignore = true)
 	MessageMetaData mapMessageMetaDataFromXtaMessageMetaData(XtaMessageMetaData xtaMessageMetaData);
 
-	@Mapping(target = "code", source = "messageTypeCode")
-	@Mapping(target = "name", ignore = true)
-	@Mapping(target = "payloadSchema", source = "messageTypePayloadSchema")
-	@Mapping(target = "listURI", constant = MESSAGE_TYPE_LIST_URI)
-	@Mapping(target = "listVersionID", constant = MESSAGE_TYPE_LIST_VERSION_ID)
-	QualifierType.MessageType mapMessageTypeQualifierType(XtaMessageMetaData xtaMessageMetaData);
-
-	@Mapping(target = "undefined", ignore = true)
-	@Mapping(target = "defined.code", source = "code")
-	@Mapping(target = "defined.listURI", constant = BUSINESS_SCENARIO_LIST_URI)
-	@Mapping(target = "defined.listVersionID", constant = BUSINESS_SCENARIO_LIST_VERSION_ID)
-	QualifierType.BusinessScenario mapBusinessScenarioQualifierType(String code);
-
 	@Mapping(target = "encryptedData", expression = "java(null)")
 	@Mapping(target = "contentContainer.message", source = "messageFile")
 	@Mapping(target = "contentContainer.attachment", source = "attachmentFiles")
@@ -97,4 +81,38 @@ public interface RequestMapper {
 	@Mapping(target = "msgSelector.messageID", expression = "java( List.of( mapAttributedURIType(string) ) )")
 	@Mapping(target = "msgPart", ignore = true)
 	MsgBoxFetchRequest mapMsgBoxFetchRequest(String messageId);
+
+	@Mapping(target = "subject", ignore = true)
+	@Mapping(target = "messageType", source = ".")
+	@Mapping(target = "businessScenario", source = ".", qualifiedByName = "mapBusinessScenario")
+	QualifierType mapQualifierType(XtaMessageMetaData messageMetaData);
+
+	@Mapping(target = "code", source = "messageTypeCode")
+	@Mapping(target = "name", ignore = true)
+	@Mapping(target = "payloadSchema", source = "messageTypePayloadSchema")
+	@Mapping(target = "listURI", constant = MESSAGE_TYPE_LIST_URI)
+	@Mapping(target = "listVersionID", constant = MESSAGE_TYPE_LIST_VERSION_ID)
+	QualifierType.MessageType mapQualifierTypeMessageType(XtaMessageMetaData messageMetaData);
+
+	@Named("mapBusinessScenario")
+	default QualifierType.BusinessScenario mapBusinessScenario(XtaMessageMetaData messageMetaData) {
+		return messageMetaData.businessScenarioListUri() != null
+				? mapDefinedBusinessScenario(messageMetaData)
+				: mapUndefinedBusinessScenario(messageMetaData);
+	}
+
+	@Mapping(target = "defined", expression = "java(null)")
+	@Mapping(target = "undefined", source = "businessScenarioCode")
+	QualifierType.BusinessScenario mapUndefinedBusinessScenario(XtaMessageMetaData messageMetaData);
+
+	@Mapping(target = "defined", source = ".", qualifiedByName = "mapDefinedBusinessScenarioCode")
+	@Mapping(target = "undefined", expression = "java(null)")
+	QualifierType.BusinessScenario mapDefinedBusinessScenario(XtaMessageMetaData messageMetaData);
+
+	@Named("mapDefinedBusinessScenarioCode")
+	@Mapping(target = "code", source = "businessScenarioCode")
+	@Mapping(target = "name", ignore = true)
+	@Mapping(target = "listURI", source = "businessScenarioListUri")
+	@Mapping(target = "listVersionID", source = "businessScenarioListVersionId")
+	KeyCodeType mapDefinedBusinessScenarioCode(XtaMessageMetaData messageMetaData);
 }
diff --git a/src/main/java/de/ozgcloud/xta/client/mapper/ResponseMapper.java b/src/main/java/de/ozgcloud/xta/client/mapper/ResponseMapper.java
index 5fa7ef6..41a88f4 100644
--- a/src/main/java/de/ozgcloud/xta/client/mapper/ResponseMapper.java
+++ b/src/main/java/de/ozgcloud/xta/client/mapper/ResponseMapper.java
@@ -41,6 +41,8 @@ public interface ResponseMapper {
 
 	@Mapping(target = "service", source = "qualifier.service")
 	@Mapping(target = "businessScenarioCode", source = "qualifier.businessScenario.defined.code")
+	@Mapping(target = "businessScenarioListUri", source = "qualifier.businessScenario.defined.listURI")
+	@Mapping(target = "businessScenarioListVersionId", source = "qualifier.businessScenario.defined.listVersionID")
 	@Mapping(target = "messageTypeCode", source = "qualifier.messageType.code")
 	@Mapping(target = "messageTypePayloadSchema", source = "qualifier.messageType.payloadSchema")
 	@Mapping(target = "messageId", source = "msgIdentification.messageID.value")
diff --git a/src/main/java/de/ozgcloud/xta/client/model/XtaMessageMetaData.java b/src/main/java/de/ozgcloud/xta/client/model/XtaMessageMetaData.java
index 707f416..aea60a3 100644
--- a/src/main/java/de/ozgcloud/xta/client/model/XtaMessageMetaData.java
+++ b/src/main/java/de/ozgcloud/xta/client/model/XtaMessageMetaData.java
@@ -2,6 +2,7 @@ package de.ozgcloud.xta.client.model;
 
 import java.math.BigInteger;
 
+import jakarta.annotation.Nullable;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
@@ -13,9 +14,11 @@ import lombok.Builder;
 public record XtaMessageMetaData(
 		@NotBlank String service,
 		@NotBlank String businessScenarioCode,
+		@Nullable String businessScenarioListUri,
+		@Nullable String businessScenarioListVersionId,
 		@NotBlank String messageTypeCode,
 		@NotBlank String messageTypePayloadSchema,
-		@NotBlank String messageId,
+		@Nullable String messageId,
 		@NotNull @Valid XtaIdentifier authorIdentifier,
 		@NotNull @Valid XtaIdentifier readerIdentifier,
 		@PositiveOrZero BigInteger messageSize
diff --git a/src/test/java/de/ozgcloud/xta/client/XtaClientManualITCase.java b/src/test/java/de/ozgcloud/xta/client/XtaClientManualITCase.java
index 51eb067..46aa778 100644
--- a/src/test/java/de/ozgcloud/xta/client/XtaClientManualITCase.java
+++ b/src/test/java/de/ozgcloud/xta/client/XtaClientManualITCase.java
@@ -10,6 +10,7 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
+import de.ozgcloud.xta.client.model.XtaMessage;
 import de.ozgcloud.xta.client.model.XtaMessageStatus;
 import genv3.de.xoev.transport.xta.x211.InvalidMessageIDException;
 import lombok.SneakyThrows;
@@ -120,5 +121,27 @@ class XtaClientManualITCase {
 
 	}
 
+	@DisplayName("send message")
+	@Nested
+	class TestSendMessage {
+
+		private final XtaMessage xtaMessage = XtaMessageExampleLoader.load(
+				XtaMessageExampleLoader.MessageExampleConfig.builder()
+						.messageLabel("dfoerdermittel")
+						.messageId(null)
+						.author(CLIENT_IDENTIFIER1)
+						.reader(CLIENT_IDENTIFIER1)
+						.build());
+
+		@DisplayName("should return with open status")
+		@Test
+		@SneakyThrows
+		void shouldReturn() {
+			var result = client.sendMessage(xtaMessage);
+
+			assertThat(result.status()).isEqualTo(XtaMessageStatus.OPEN);
+		}
+	}
+
 }
 
diff --git a/src/test/java/de/ozgcloud/xta/client/XtaClientTest.java b/src/test/java/de/ozgcloud/xta/client/XtaClientTest.java
index 4d1bd7a..936315e 100644
--- a/src/test/java/de/ozgcloud/xta/client/XtaClientTest.java
+++ b/src/test/java/de/ozgcloud/xta/client/XtaClientTest.java
@@ -19,7 +19,9 @@ import org.mockito.junit.jupiter.MockitoExtension;
 
 import de.ozgcloud.xta.client.config.XtaClientConfig;
 import de.ozgcloud.xta.client.core.WrappedXtaService;
+import de.ozgcloud.xta.client.factory.XtaMessageTestFactory;
 import de.ozgcloud.xta.client.model.XtaMessage;
+import de.ozgcloud.xta.client.model.XtaMessageMetaData;
 import de.ozgcloud.xta.client.model.XtaMessageMetaDataListing;
 import de.ozgcloud.xta.client.model.XtaTransportReport;
 import lombok.SneakyThrows;
@@ -168,4 +170,86 @@ class XtaClientTest {
 		}
 	}
 
+	@DisplayName("send message")
+	@Nested
+	class TestSendMessage {
+
+		@Mock
+		XtaMessage xtaMessageWithoutMessageId;
+
+		@Mock
+		XtaMessageMetaData xtaMessageMetaDataWithoutMessageId;
+
+		@Mock
+		XtaMessage xtaMessage;
+
+		@Mock
+		XtaTransportReport xtaTransportReport;
+
+		@BeforeEach
+		@SneakyThrows
+		void mock() {
+			when(xtaMessageWithoutMessageId.metaData()).thenReturn(xtaMessageMetaDataWithoutMessageId);
+			when(xtaMessageMetaDataWithoutMessageId.authorIdentifier()).thenReturn(AUTHOR_IDENTIFIER);
+			when(xtaMessageMetaDataWithoutMessageId.readerIdentifier()).thenReturn(READER_IDENTIFIER);
+			when(xtaMessageMetaDataWithoutMessageId.service()).thenReturn(MESSAGE_SERVICE);
+
+			when(service.createMessageId(AUTHOR_IDENTIFIER)).thenReturn(MESSAGE_ID);
+			doReturn(xtaMessage).when(client).createXtaMessageWithMessageId(xtaMessageWithoutMessageId, MESSAGE_ID);
+			when(service.getTransportReport(MESSAGE_ID, AUTHOR_IDENTIFIER)).thenReturn(xtaTransportReport);
+		}
+
+		@DisplayName("should call checkAccountActive")
+		@Test
+		@SneakyThrows
+		void shouldCallCheckAccountActive() {
+			client.sendMessage(xtaMessageWithoutMessageId);
+
+			verify(service).checkAccountActive(AUTHOR_IDENTIFIER);
+		}
+
+		@DisplayName("should call lookup service")
+		@Test
+		@SneakyThrows
+		void shouldCallLookupService() {
+			client.sendMessage(xtaMessageWithoutMessageId);
+
+			verify(service).lookupService(MESSAGE_SERVICE, READER_IDENTIFIER, AUTHOR_IDENTIFIER);
+		}
+
+		@DisplayName("should call send message")
+		@Test
+		@SneakyThrows
+		void shouldCallSendMessage() {
+			client.sendMessage(xtaMessageWithoutMessageId);
+
+			verify(service).sendMessage(xtaMessage);
+		}
+
+		@DisplayName("should return with transport report")
+		@Test
+		@SneakyThrows
+		void shouldReturnWithTransportReport() {
+			var result = client.sendMessage(xtaMessageWithoutMessageId);
+
+			assertThat(result).isEqualTo(xtaTransportReport);
+		}
+	}
+
+	@DisplayName("create xta message with message id")
+	@Nested
+	class TestCreateXtaMessageWithMessageId {
+		private final XtaMessage xtaMessage = XtaMessageTestFactory.create();
+
+		@DisplayName("should set message id")
+		@Test
+		void shouldSetMessageId() {
+			var NEW_MESSAGE_ID = "newMessageId";
+
+			var result = client.createXtaMessageWithMessageId(xtaMessage, NEW_MESSAGE_ID);
+
+			assertThat(result.metaData().messageId()).isEqualTo(NEW_MESSAGE_ID);
+		}
+	}
+
 }
\ No newline at end of file
diff --git a/src/test/java/de/ozgcloud/xta/client/XtaMessageExampleLoader.java b/src/test/java/de/ozgcloud/xta/client/XtaMessageExampleLoader.java
index 4dfbf02..7fb70cf 100644
--- a/src/test/java/de/ozgcloud/xta/client/XtaMessageExampleLoader.java
+++ b/src/test/java/de/ozgcloud/xta/client/XtaMessageExampleLoader.java
@@ -25,8 +25,8 @@ import org.apache.commons.io.IOUtils;
 import org.jetbrains.annotations.NotNull;
 import org.yaml.snakeyaml.Yaml;
 
-import de.ozgcloud.xta.client.model.XtaIdentifier;
 import de.ozgcloud.xta.client.model.XtaFile;
+import de.ozgcloud.xta.client.model.XtaIdentifier;
 import de.ozgcloud.xta.client.model.XtaMessage;
 import de.ozgcloud.xta.client.model.XtaMessageMetaData;
 import lombok.Builder;
@@ -112,10 +112,12 @@ public class XtaMessageExampleLoader {
 		return XtaMessageMetaData.builder()
 				.service(getString.apply("service"))
 				.businessScenarioCode(getString.apply("businessScenarioCode"))
+				.businessScenarioListUri(getString.apply("businessScenarioListUri"))
+				.businessScenarioListVersionId(getString.apply("businessScenarioListVersionId"))
 				.messageTypeCode(getString.apply("messageTypeCode"))
 				.messageTypePayloadSchema(getString.apply("messageTypePayloadSchema"))
 				.messageId(getIfConfigNull(
-						config.messageId, () -> getString.apply("messageId")))
+						config.messageId, () -> MapUtils.getString(metaData, "messageId")))
 				.authorIdentifier(getIfConfigNull(
 						config.author,
 						() -> mapIdentifier(getChild(metaData, "authorIdentifier"))))
diff --git a/src/test/java/de/ozgcloud/xta/client/core/RequestMapperTest.java b/src/test/java/de/ozgcloud/xta/client/core/RequestMapperTest.java
index 06958cf..0eb0570 100644
--- a/src/test/java/de/ozgcloud/xta/client/core/RequestMapperTest.java
+++ b/src/test/java/de/ozgcloud/xta/client/core/RequestMapperTest.java
@@ -183,6 +183,34 @@ class RequestMapperTest {
 					mapper.mapPartyIdentifierTypeFromIdentifier(READER_IDENTIFIER));
 		}
 
+		@DisplayName("with undefined business scenario")
+		@Nested
+		class TestWithUndefinedBusinessScenario {
+			@DisplayName("should map code")
+			@Test
+			void shouldMapCode() {
+				var result = mapWithUndefinedBusinessScenario();
+
+				assertThat(result.getQualifier().getBusinessScenario().getUndefined()).isEqualTo(BUSINESS_SCENARIO_CODE);
+			}
+
+			@DisplayName("should map defined to null")
+			@Test
+			void shouldMapDefinedToNull() {
+				var result = mapWithUndefinedBusinessScenario();
+
+				assertThat(result.getQualifier().getBusinessScenario().getDefined()).isNull();
+			}
+
+			private MessageMetaData mapWithUndefinedBusinessScenario() {
+				var metaData = XtaMessageMetaDataTestFactory.createBuilder()
+						.businessScenarioListUri(null)
+						.build();
+
+				return mapper.mapMessageMetaDataFromXtaMessageMetaData(metaData);
+			}
+		}
+
 		private MessageMetaData map() {
 			return mapper.mapMessageMetaDataFromXtaMessageMetaData(XtaMessageMetaDataTestFactory.create());
 		}
diff --git a/src/test/java/de/ozgcloud/xta/client/core/ResponseMapperTest.java b/src/test/java/de/ozgcloud/xta/client/core/ResponseMapperTest.java
index 0dc5ebd..79f314f 100644
--- a/src/test/java/de/ozgcloud/xta/client/core/ResponseMapperTest.java
+++ b/src/test/java/de/ozgcloud/xta/client/core/ResponseMapperTest.java
@@ -134,6 +134,22 @@ class ResponseMapperTest {
 			assertThat(result.businessScenarioCode()).isEqualTo(BUSINESS_SCENARIO_CODE);
 		}
 
+		@DisplayName("should map business scenario list uri")
+		@Test
+		void shouldMapBusinessScenarioListUri() {
+			var result = doMapping();
+
+			assertThat(result.businessScenarioListUri()).isEqualTo(BUSINESS_SCENARIO_LIST_URI);
+		}
+
+		@DisplayName("should map business scenario list version id")
+		@Test
+		void shouldMapBusinessScenarioListVersionId() {
+			var result = doMapping();
+
+			assertThat(result.businessScenarioListVersionId()).isEqualTo(BUSINESS_SCENARIO_LIST_VERSION_ID);
+		}
+
 		@DisplayName("should map message type payload schema")
 		@Test
 		void shouldMapMessageTypePayloadSchema() {
diff --git a/src/test/java/de/ozgcloud/xta/client/factory/MessageMetaDataTestFactory.java b/src/test/java/de/ozgcloud/xta/client/factory/MessageMetaDataTestFactory.java
index e8f44dd..a4eac2f 100644
--- a/src/test/java/de/ozgcloud/xta/client/factory/MessageMetaDataTestFactory.java
+++ b/src/test/java/de/ozgcloud/xta/client/factory/MessageMetaDataTestFactory.java
@@ -14,6 +14,8 @@ public class MessageMetaDataTestFactory {
 
 	public static final String MESSAGE_TYPE_PAYLOAD_SCHEMA = "message-type-payload-schema";
 	public static final String BUSINESS_SCENARIO_CODE = "businessScenarioCode";
+	public static final String BUSINESS_SCENARIO_LIST_URI = "urn:de:dataport:codeliste:business.scenario";
+	public static final String BUSINESS_SCENARIO_LIST_VERSION_ID = "1.0";
 
 	public static final XtaIdentifier AUTHOR_IDENTIFIER = XtaIdentifier.builder()
 			.value("authorIdentifier")
diff --git a/src/test/java/de/ozgcloud/xta/client/factory/XtaMessageMetaDataTestFactory.java b/src/test/java/de/ozgcloud/xta/client/factory/XtaMessageMetaDataTestFactory.java
index 9a13990..45eafd5 100644
--- a/src/test/java/de/ozgcloud/xta/client/factory/XtaMessageMetaDataTestFactory.java
+++ b/src/test/java/de/ozgcloud/xta/client/factory/XtaMessageMetaDataTestFactory.java
@@ -14,6 +14,8 @@ public class XtaMessageMetaDataTestFactory {
 		return XtaMessageMetaData.builder()
 				.service(MESSAGE_SERVICE)
 				.businessScenarioCode(BUSINESS_SCENARIO_CODE)
+				.businessScenarioListUri(BUSINESS_SCENARIO_LIST_URI)
+				.businessScenarioListVersionId(BUSINESS_SCENARIO_LIST_VERSION_ID)
 				.messageTypeCode(MESSAGE_TYPE_CODE)
 				.messageTypePayloadSchema(MESSAGE_TYPE_PAYLOAD_SCHEMA)
 				.messageId(MESSAGE_ID)
diff --git a/src/test/resources/messages/dfoerdermittel/xta-message.yaml b/src/test/resources/messages/dfoerdermittel/xta-message.yaml
index 96b22b9..c10df10 100644
--- a/src/test/resources/messages/dfoerdermittel/xta-message.yaml
+++ b/src/test/resources/messages/dfoerdermittel/xta-message.yaml
@@ -1,6 +1,8 @@
 metaData:
   service: urn:xoev-de:xdomea:schema:2.4.0/xdomea240Antrag.wsdl
   businessScenarioCode: XDOMEAGAD_DATA
+  businessScenarioListUri: urn:de:dataport:codeliste:business.scenario
+  businessScenarioListVersionId: 1.0
   messageTypeCode: Geschaeftsgang.Geschaeftsgang.0201
   messageTypePayloadSchema: urn:xoev-de:xdomea:schema:2.4.0
   authorIdentifier:
diff --git a/src/test/resources/messages/versammlungsanzeige/xta-message.yaml b/src/test/resources/messages/versammlungsanzeige/xta-message.yaml
index 895b64f..b48b76d 100644
--- a/src/test/resources/messages/versammlungsanzeige/xta-message.yaml
+++ b/src/test/resources/messages/versammlungsanzeige/xta-message.yaml
@@ -3,6 +3,8 @@ metaData:
   businessScenarioCode: FIM_DATA
   messageTypeCode: fim.S17000652.17000652001004
   messageTypePayloadSchema: urn:xoev-de:xfall:standard:fim-s17000652_1.4
+  businessScenarioListUri: urn:de:dataport:codeliste:business.scenario
+  businessScenarioListVersionId: 1
   authorIdentifier:
     name: Dataport
     category: Engagement- und Hobbyportal
-- 
GitLab