diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/fim/FimMessageMapper.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/fim/FimMessageMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..5547fcee5ab000b7ac1e15f5fb07027467211ae3
--- /dev/null
+++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/fim/FimMessageMapper.java
@@ -0,0 +1,43 @@
+package de.ozgcloud.eingang.fim;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.common.formdata.FormHeader;
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
+import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle;
+import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier;
+import de.ozgcloud.eingang.xta.XtaMessageMetaData;
+
+@Component
+public class FimMessageMapper {
+	private static final int VORGANG_NUMMER_SUFFIX_LENGTH = 4;
+
+	/*
+	 * FIXME: This is only a quick and dirty implementation for a fim message mapper
+	 */
+	public FormData toFormData(final XtaMessageMetaData metaData, final VorgangNummerSupplier vorgangNummerSupplier,
+			final Collection<IncomingFile> incomingFileList) {
+		return FormData.builder()
+				.header(FormHeader.builder()
+						.formId(metaData.getMessageType())
+						.requestId(metaData.getMessageId().toString())
+						.createdAt(metaData.getOrigin())
+						.vorgangNummer(vorgangNummerSupplier.get(VORGANG_NUMMER_SUFFIX_LENGTH))
+						.sender("XTA")
+						.build())
+				.zustaendigeStelle(ZustaendigeStelle.builder()
+						.organisationseinheitenId("0")
+						.build())
+				.numberOfAttachments(incomingFileList.size())
+				.attachments(Collections.singleton(IncomingFileGroup.builder()
+						.name("fim_files")
+						.files(incomingFileList)
+						.build()))
+				.build();
+	}
+}
diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/fim/FimXtaMessageHandler.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/fim/FimXtaMessageHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..53bcc14262dc99cefa72093448f8135f0628bbdf
--- /dev/null
+++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/fim/FimXtaMessageHandler.java
@@ -0,0 +1,34 @@
+package de.ozgcloud.eingang.fim;
+
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier;
+import de.ozgcloud.eingang.xta.XtaMessageHandler;
+import de.ozgcloud.eingang.xta.XtaMessageMetaData;
+
+@Component
+public class FimXtaMessageHandler implements XtaMessageHandler {
+	static final String ALL_FIM_MESSAGES_PREFIX = "fim.";
+
+	@Autowired
+	private FimMessageMapper fimMessageMapper;
+
+	@Autowired
+	private VorgangNummerSupplier vorgangNummerSupplier;
+
+	@Override
+	public FormData getFormData(XtaMessageMetaData xtaMessageMetaData, List<IncomingFile> incomingFiles) {
+		return fimMessageMapper.toFormData(xtaMessageMetaData, vorgangNummerSupplier, incomingFiles);
+	}
+
+	@Override
+	public boolean isResponsible(XtaMessageMetaData xtaMessageMetaData) {
+		return StringUtils.startsWith(xtaMessageMetaData.getMessageType(), ALL_FIM_MESSAGES_PREFIX);
+	}
+}
diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaXtaMessageHandler.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaXtaMessageHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..382ac8247ebae63f7868a9ea274a4644a7fead4c
--- /dev/null
+++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XdomeaXtaMessageHandler.java
@@ -0,0 +1,38 @@
+package de.ozgcloud.eingang.xdomea;
+
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier;
+import de.ozgcloud.eingang.xta.XtaMessageHandler;
+import de.ozgcloud.eingang.xta.XtaMessageMetaData;
+
+@Component
+public class XdomeaXtaMessageHandler implements XtaMessageHandler {
+	static final String XDOMEA_0201_MESSAGE_TYPE = "Geschaeftsgang.Geschaeftsgang.0201";
+
+	@Autowired
+	private XtaMessageMapper xtaMessageMapper;
+
+	@Autowired
+	private XdomeaMessageDataMapper xdomeaMessageDataMapper;
+
+	@Autowired
+	private VorgangNummerSupplier vorgangNummerSupplier;
+
+	@Override
+	public FormData getFormData(XtaMessageMetaData xtaMessageMetaData, List<IncomingFile> incomingFiles) {
+		var xdomeaMessageData = xdomeaMessageDataMapper.mapIncomingFilesToXdomeaMessageData(incomingFiles);
+		return xtaMessageMapper.toFormData(xdomeaMessageData, xtaMessageMetaData, vorgangNummerSupplier);
+	}
+
+	@Override
+	public boolean isResponsible(XtaMessageMetaData xtaMessageMetaData) {
+		return StringUtils.equals(xtaMessageMetaData.getMessageType(), XDOMEA_0201_MESSAGE_TYPE);
+	}
+}
diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMapper.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XtaMessageMapper.java
similarity index 94%
rename from xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMapper.java
rename to xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XtaMessageMapper.java
index af561ff948a92bee781a4745cd9b98af4ece0c8e..61ad8a17c0b2ef0ce894b64a974983b3ee9b72a9 100644
--- a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMapper.java
+++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xdomea/XtaMessageMapper.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.eingang.xta;
+package de.ozgcloud.eingang.xdomea;
 
 import java.util.List;
 import java.util.stream.Stream;
@@ -12,7 +12,8 @@ import de.ozgcloud.eingang.common.formdata.FormHeader;
 import de.ozgcloud.eingang.common.formdata.IncomingFile;
 import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier;
 import de.ozgcloud.eingang.semantik.enginebased.FilesMapperHelper;
-import de.ozgcloud.eingang.xdomea.XdomeaMessageData;
+import de.ozgcloud.eingang.xta.XtaMessageId;
+import de.ozgcloud.eingang.xta.XtaMessageMetaData;
 
 @Mapper(imports = FilesMapperHelper.class)
 interface XtaMessageMapper {
diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/FimMessageMapper.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/FimMessageMapper.java
deleted file mode 100644
index 0bd2ef454ec3ab14fea971fa424c273710a7f563..0000000000000000000000000000000000000000
--- a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/FimMessageMapper.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package de.ozgcloud.eingang.xta;
-
-import de.ozgcloud.eingang.common.formdata.FormData;
-import de.ozgcloud.eingang.common.formdata.FormHeader;
-import de.ozgcloud.eingang.common.formdata.IncomingFile;
-
-import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
-import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier;
-import org.springframework.stereotype.Component;
-
-import java.util.Collection;
-import java.util.Collections;
-
-import static de.ozgcloud.eingang.xta.XtaMessageMapper.VORGANG_NUMMER_SUFFIX_LENGTH;
-
-@Component
-public class FimMessageMapper {
-
-    /*
-     * FIXME: This is only a quick and dirty implementation for a fim message mapper
-     */
-    public FormData toFormData(final XtaMessageMetaData metaData, final VorgangNummerSupplier vorgangNummerSupplier, final Collection<IncomingFile> incomingFileList) {
-        return FormData.builder()
-                .header(FormHeader.builder()
-                        .formId(metaData.getMessageType())
-                        .requestId(metaData.getMessageId().toString())
-                        .createdAt(metaData.getOrigin())
-                        .vorgangNummer(vorgangNummerSupplier.get(VORGANG_NUMMER_SUFFIX_LENGTH))
-                        .sender("XTA")
-                        .build())
-                .numberOfAttachments(incomingFileList.size())
-                .attachments(Collections.singleton(IncomingFileGroup.builder()
-                        .name("fim_files")
-                        .files(incomingFileList)
-                        .build()))
-                .build();
-    }
-}
diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageHandler.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..73cbae25ae23a28838d23c8c79aa8c9d39477c84
--- /dev/null
+++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageHandler.java
@@ -0,0 +1,13 @@
+package de.ozgcloud.eingang.xta;
+
+import java.util.List;
+
+import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+
+public interface XtaMessageHandler {
+
+	FormData getFormData(XtaMessageMetaData xtaMessageMetaData, List<IncomingFile> incomingFiles);
+
+	boolean isResponsible(XtaMessageMetaData xtaMessageMetaData);
+}
diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMetaData.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMetaData.java
index 66d4ed8d011521b3895e738a3eaf7d91b35af8fa..ec33b3cfb5d8ddfa65131824f9a8c1a99d948b2a 100644
--- a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMetaData.java
+++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaMessageMetaData.java
@@ -7,7 +7,7 @@ import lombok.Getter;
 
 @Builder
 @Getter
-class XtaMessageMetaData {
+public class XtaMessageMetaData {
 	// MsgIdentification.MessageId
 	private XtaMessageId messageId;
 	// DeliveryAttributes.origin
diff --git a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaService.java b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaService.java
index dd3b1daf032fc8dd146d0f043a3be253f7cf47af..ca949b15084effa0b3ad1cf3e6bb178126b1d852 100644
--- a/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaService.java
+++ b/xta-adapter/src/main/java/de/ozgcloud/eingang/xta/XtaService.java
@@ -1,12 +1,11 @@
 package de.ozgcloud.eingang.xta;
 
+import java.util.List;
+import java.util.Optional;
 import java.util.Spliterators;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 
-import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier;
-import de.ozgcloud.eingang.xdomea.XdomeaMessageDataMapper;
-import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -17,26 +16,21 @@ import lombok.extern.log4j.Log4j2;
 @Service
 @Log4j2
 class XtaService {
-
-	static final String XDOMEA_0201_MESSAGE_TYPE = "Geschaeftsgang.Geschaeftsgang.0201";
-
-	static final String ALL_FIM_MESSAGES_PREFIX = "fim.";
-
 	@Autowired
 	private XtaRemoteService remoteService;
-	@Autowired
-	private XtaMessageMapper mapper;
-	@Autowired
-	private VorgangNummerSupplier vorgangNummerSupplier;
-	@Autowired
-	private XdomeaMessageDataMapper xdomeaMessageDataMapper;
-	@Autowired
-	private FimMessageMapper fimMessageMapper;
+
 	@Autowired
 	private XtaIncomingFilesMapper xtaIncomingFilesMapper;
 
+	@Autowired
+	private List<XtaMessageHandler> xtaMessageHandlers;
+
 	public Stream<FormData> getMessages() {
-		return createXtaMessageStream().filter(this::isSupportedMessageType).map(this::getFormData);
+		return createXtaMessageStream().map(this::mapToFormData).flatMap(Optional::stream);
+	}
+
+	Optional<FormData> mapToFormData(XtaMessageMetaData messageMetaData) {
+		return getResponsibleHandler(messageMetaData).map(handler -> getFormData(messageMetaData, handler));
 	}
 
 	Stream<XtaMessageMetaData> createXtaMessageStream() {
@@ -44,21 +38,24 @@ class XtaService {
 		return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
 	}
 
-	boolean isSupportedMessageType(XtaMessageMetaData metaData) {
-		if (StringUtils.startsWith(metaData.getMessageType(), ALL_FIM_MESSAGES_PREFIX)) {
-			return true;
+	Optional<XtaMessageHandler> getResponsibleHandler(XtaMessageMetaData messageMetaData) {
+		var handlerOptional = xtaMessageHandlers.stream()
+				.filter(handler -> handler.isResponsible(messageMetaData))
+				.findFirst();
+		if (handlerOptional.isEmpty()) {
+			logWarningForUnsupportedMessageType(messageMetaData.getMessageType());
 		}
+		return handlerOptional;
+	}
 
-		LOG.warn("Ignoring XTA-Message of type '{}'.", metaData.getMessageType());
-		return false;
+	void logWarningForUnsupportedMessageType(String messageType) {
+		LOG.warn("Ignoring XTA-Message of type '{}'.", messageType);
 	}
 
-	public FormData getFormData(@NonNull XtaMessageMetaData metaData) {
+	FormData getFormData(@NonNull XtaMessageMetaData metaData, XtaMessageHandler handler) {
 		var msg = remoteService.getMessage(metaData.getMessageId());
 		var incomingFiles = xtaIncomingFilesMapper.toIncomingFiles(msg.getMessageFiles());
-
-		// FIXME should be called based on messageType and not hard coded
-		return fimMessageMapper.toFormData(metaData, vorgangNummerSupplier, incomingFiles);
+		return handler.getFormData(metaData, incomingFiles);
 	}
 
 	public void acknowledgeReceive(@NonNull XtaMessageId messageId) {
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaXtaMessageHandlerTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaXtaMessageHandlerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..ce0ac7066ad3db6c62e92ef874420ab70d7c4fc3
--- /dev/null
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XdomeaXtaMessageHandlerTest.java
@@ -0,0 +1,86 @@
+package de.ozgcloud.eingang.xdomea;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.util.List;
+
+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.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
+import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier;
+import de.ozgcloud.eingang.xta.XtaMessageMetaData;
+
+class XdomeaXtaMessageHandlerTest {
+
+	@Spy
+	@InjectMocks
+	private XdomeaXtaMessageHandler handler;
+
+	@Mock
+	private XtaMessageMapper xtaMessageMapper;
+
+	@Mock
+	private XdomeaMessageDataMapper xdomeaMessageDataMapper;
+
+	@Mock
+	private VorgangNummerSupplier vorgangNummerSupplier;
+
+	@Mock
+	private XtaMessageMetaData xtaMessageMetaData;
+
+	@DisplayName("get form data")
+	@Nested
+	class TestGetFormData {
+
+		@Mock
+		private List<IncomingFile> incomingFiles;
+
+		@Mock
+		private XdomeaMessageData xdomeaMessageData;
+
+		@Mock
+		private FormData formData;
+
+		@DisplayName("should map to form data")
+		@Test
+		void shouldMapToFormData() {
+			when(xdomeaMessageDataMapper.mapIncomingFilesToXdomeaMessageData(incomingFiles)).thenReturn(xdomeaMessageData);
+			when(xtaMessageMapper.toFormData(xdomeaMessageData, xtaMessageMetaData, vorgangNummerSupplier)).thenReturn(formData);
+
+			var result = handler.getFormData(xtaMessageMetaData, incomingFiles);
+
+			assertThat(result).isEqualTo(formData);
+		}
+	}
+
+	@DisplayName("is responsible")
+	@Nested
+	class TestIsResponsible {
+		@DisplayName("should return true for 0201")
+		@Test
+		void shouldReturnTrueFor0201() {
+			when(xtaMessageMetaData.getMessageType()).thenReturn(XdomeaXtaMessageHandler.XDOMEA_0201_MESSAGE_TYPE);
+
+			var result = handler.isResponsible(xtaMessageMetaData);
+
+			assertThat(result).isTrue();
+		}
+
+		@DisplayName("should return false for other")
+		@Test
+		void shouldReturnFalseForOther() {
+			when(xtaMessageMetaData.getMessageType()).thenReturn("other");
+
+			var result = handler.isResponsible(xtaMessageMetaData);
+
+			assertThat(result).isFalse();
+		}
+	}
+}
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMapperTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XtaMessageMapperTest.java
similarity index 84%
rename from xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMapperTest.java
rename to xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XtaMessageMapperTest.java
index b9bcda822a302872474e1c4341cbe08b11675b99..30438a770dee699e490dc461fb727168692ad81c 100644
--- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMapperTest.java
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xdomea/XtaMessageMapperTest.java
@@ -1,6 +1,6 @@
-package de.ozgcloud.eingang.xta;
+package de.ozgcloud.eingang.xdomea;
 
-import static de.ozgcloud.eingang.xta.XtaMessageMapper.*;
+import static de.ozgcloud.eingang.xdomea.XtaMessageMapper.*;
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
 
@@ -14,8 +14,9 @@ import org.mockito.Spy;
 
 import de.ozgcloud.eingang.common.formdata.FormData;
 import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier;
-import de.ozgcloud.eingang.xdomea.XdomeaMessageDataTestFactory;
-import de.ozgcloud.eingang.xdomea.XdomeaMessageData;
+import de.ozgcloud.eingang.xta.FormHeaderTestFactory;
+import de.ozgcloud.eingang.xta.XtaMessageMetaData;
+import de.ozgcloud.eingang.xta.XtaMessageMetaDataTestFactory;
 
 class XtaMessageMapperTest {
 
@@ -43,7 +44,8 @@ class XtaMessageMapperTest {
 		void shouldMapRepresentations() {
 			var formData = doMapping();
 
-			assertThat(formData.getRepresentations()).containsExactly(xdomeaMessageData.metadataFile(), xdomeaMessageData.representations().getFirst());
+			assertThat(formData.getRepresentations()).containsExactly(xdomeaMessageData.metadataFile(),
+					xdomeaMessageData.representations().getFirst());
 		}
 
 		@Test
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/FormHeaderTestFactory.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/FormHeaderTestFactory.java
index acd02b8efce3f09542c8dc5c748850027ad27072..7787f4f7adbf36bef0bbf9d0550293c9aefb2ea0 100644
--- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/FormHeaderTestFactory.java
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/FormHeaderTestFactory.java
@@ -6,7 +6,7 @@ import de.ozgcloud.eingang.common.formdata.FormHeader.FormHeaderBuilder;
 public class FormHeaderTestFactory {
 
 	private static final String FORM_NAME = "xdomea";
-	static final String VORGANGNUMMER = "vorgangNummer";
+	public static final String VORGANGNUMMER = "vorgangNummer";
 
 	static FormHeader create() {
 		return createBuilder().build();
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaITCase.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaITCase.java
index 6a5705a31bc4ea95c96227e291f3d4b3e814da45..7cde20ce00d187d79df663ba10c6e00fbf8ff26f 100644
--- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaITCase.java
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaITCase.java
@@ -13,6 +13,7 @@ import java.util.Optional;
 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.ArgumentCaptor;
@@ -148,6 +149,17 @@ class XtaITCase {
 			assertThat(vorgangNummer).hasSize(9);
 		}
 
+		@DisplayName("should use xta vorgangsnummer for FIM")
+		@Test
+		void shouldUseGenerated() {
+			mockNachrichtenBroker("versammlungsanzeige.xml");
+
+			runner.runGetXtaMessages();
+
+			var vorgangNummer = captureEingang().getHeader().getVorgangNummer();
+			assertThat(vorgangNummer).hasSize(9);
+		}
+
 		private GrpcEingang captureEingang() {
 			verify(vorgangRemoteService, times(1))
 					.createVorgang(
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataTestFactory.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataTestFactory.java
index d112294af7ba77c619baf1b9574a648ac1930b1f..dc78ddbe98e757c2fd2416527c3d5d470bb7a5f1 100644
--- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataTestFactory.java
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaMessageMetaDataTestFactory.java
@@ -4,16 +4,16 @@ import static de.ozgcloud.eingang.xta.XtaMessageTestFactory.*;
 
 import java.time.ZonedDateTime;
 
-class XtaMessageMetaDataTestFactory {
+public class XtaMessageMetaDataTestFactory {
 
 	static final String MESSAGE_TYPE = "Geschaeftsgang.Geschaeftsgang.0201";
 	static final ZonedDateTime ORIGIN = ZonedDateTime.parse("2022-10-29T15:45:52.4942149+02:00");
 
-	static XtaMessageMetaData create() {
+	public static XtaMessageMetaData create() {
 		return createBuilder().build();
 	}
 
-	static XtaMessageMetaData.XtaMessageMetaDataBuilder createBuilder() {
+	public static XtaMessageMetaData.XtaMessageMetaDataBuilder createBuilder() {
 		return XtaMessageMetaData.builder()
 				.messageId(MESSAGE_ID)
 				.messageType(MESSAGE_TYPE)
diff --git a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaServiceTest.java b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaServiceTest.java
index 9546bb7aeefa8cdf72cce07c6709ced1ffa62e7b..d0691612d792425fd288fd3e067cdbd1bd47864b 100644
--- a/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaServiceTest.java
+++ b/xta-adapter/src/test/java/de/ozgcloud/eingang/xta/XtaServiceTest.java
@@ -1,183 +1,201 @@
 package de.ozgcloud.eingang.xta;
 
 import static org.assertj.core.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
 import java.util.List;
+import java.util.Optional;
 import java.util.stream.Stream;
 
 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.ArgumentCaptor;
-import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
-import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory;
-import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier;
-import de.ozgcloud.eingang.xdomea.XdomeaMessageData;
-import de.ozgcloud.eingang.xdomea.XdomeaMessageDataTestFactory;
-import de.ozgcloud.eingang.xdomea.XdomeaMessageDataMapper;
+import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.common.formdata.IncomingFile;
 
 class XtaServiceTest {
 
-	private static final String MESSAGE_TYPE_OTHER = "MESSAGE_TYPE_OTHER";
-
 	@Spy
 	@InjectMocks
 	private XtaService service;
 
+	@Mock
+	private List<XtaMessageHandler> xtaMessageHandlers;
+
 	@Mock
 	private XtaRemoteService remoteService;
+
 	@Mock
-	private XtaMessageMapper mapper;
+	private XtaIncomingFilesMapper incomingFilesMapper;
+
 	@Mock
-	private VorgangNummerSupplier vorgangNummerSupplier;
+	private XtaMessageHandler messageHandler1;
 
 	@Mock
-	private XtaIncomingFilesMapper incomingFilesMapper;
+	private XtaMessageHandler messageHandler2;
 
 	@Mock
-	private XdomeaMessageDataMapper xdomeaMessageDataMapper;
+	private FormData formData;
 
+	@DisplayName("get messages")
 	@Nested
-	class TestGetMessagesAsFormData {
+	class TestGetMessages {
 
-		private final XtaMessageMetaData messageMetaData = XtaMessageMetaDataTestFactory.create();
-		private final XtaMessage message = XtaMessageTestFactory.create();
+		@Mock
+		XtaMessageMetaData messageMetaData;
 
-		@BeforeEach
-		void setup() {
+		@DisplayName("should return stream of FormData")
+		@Test
+		void shouldReturnStreamOfFormData() {
 			doReturn(Stream.of(messageMetaData)).when(service).createXtaMessageStream();
-		}
+			doReturn(Optional.of(formData)).when(service).mapToFormData(messageMetaData);
 
-		@Test
-		void shouldCallCreateStream() {
-			service.getMessages();
+			var result = service.getMessages().toList();
 
-			verify(service).createXtaMessageStream();
+			assertThat(result).containsExactly(formData);
 		}
 
+		@DisplayName("should return empty stream if no FormData optional")
 		@Test
-		void shouldCallFilterByMessageType() {
-			setupMocks();
+		void shouldReturnEmptyStreamIfNoFormDataOptional() {
+			doReturn(Stream.of(messageMetaData)).when(service).createXtaMessageStream();
+			doReturn(Optional.empty()).when(service).mapToFormData(messageMetaData);
 
-			service.getMessages().toList();
+			var result = service.getMessages().toList();
 
-			verify(service).isSupportedMessageType(messageMetaData);
+			assertThat(result).isEmpty();
 		}
+	}
+
+	@DisplayName("map to form data")
+	@Nested
+	class TestMapToFormData {
+
+		@Mock
+		private XtaMessageMetaData xtaMessageMetaData;
 
+		@DisplayName("should return FormData from responsible handler")
 		@Test
-		void shouldCallGetFormData() {
-			setupMocks();
-			doReturn(true).when(service).isSupportedMessageType(messageMetaData);
+		void shouldReturnFormDataFromResponsibleHandler() {
+			doReturn(Optional.of(messageHandler1)).when(service).getResponsibleHandler(xtaMessageMetaData);
+			doReturn(formData).when(service).getFormData(xtaMessageMetaData, messageHandler1);
 
-			service.getMessages().toList();
+			var result = service.mapToFormData(xtaMessageMetaData);
 
-			verify(service).getFormData(messageMetaData);
+			assertThat(result).contains(formData);
 		}
 
+		@DisplayName("should return empty if no responsible handler")
 		@Test
-		void shouldNotCallGetFormData() {
-			doReturn(false).when(service).isSupportedMessageType(messageMetaData);
+		void shouldReturnEmptyIfNoResponsibleHandler() {
+			doReturn(Optional.empty()).when(service).getResponsibleHandler(xtaMessageMetaData);
 
-			service.getMessages().toList();
+			var result = service.mapToFormData(xtaMessageMetaData);
 
-			verify(service, never()).getFormData(any());
-		}
-
-		private void setupMocks() {
-			var testFormData = FormDataTestFactory.create();
-			when(mapper.toFormData(any(), any(), eq(vorgangNummerSupplier))).thenReturn(testFormData);
-			when(remoteService.getMessage(any(XtaMessageId.class))).thenReturn(message);
+			assertThat(result).isEmpty();
 		}
 	}
 
+	@DisplayName("create XTA message stream")
 	@Nested
-	class TestIsSupportedMessageType {
+	class TestCreateXtaMessageStream {
 
-		@Test
-		void shouldAcceptDFoerdermittel() {
-			var metaDataDFoerder = XtaMessageMetaDataTestFactory.create();
-
-			assertThat(service.isSupportedMessageType(metaDataDFoerder)).isTrue();
-		}
+		@Mock
+		private XtaMessageMetaDatasAndHeader messagesMetaData;
 
+		@DisplayName("should return stream of XtaMessageMetaData")
 		@Test
-		void shouldAcceptFimMessageType() {
-			var metaDataVersammlungsanzeige = VersammlungsanzeigeMetaDataTestFactory.create();
+		void shouldReturnStreamOfXtaMessageMetaData() {
+			var message = XtaMessageMetaDataTestFactory.create();
+			when(remoteService.getMessagesMetadata()).thenReturn(messagesMetaData);
+			when(messagesMetaData.getMessages()).thenReturn(Stream.of(message));
 
-			assertThat(service.isSupportedMessageType(metaDataVersammlungsanzeige)).isTrue();
-		}
+			var result = service.createXtaMessageStream().toList();
 
-		@Test
-		void shouldNotAcceptOtherMessageType() {
-			var metaDataDFoerder = XtaMessageMetaDataTestFactory.createBuilder().messageType(MESSAGE_TYPE_OTHER).build();
-
-			assertThat(service.isSupportedMessageType(metaDataDFoerder)).isFalse();
+			assertThat(result).containsExactly(message);
 		}
 	}
 
+	@DisplayName("get responsible handler")
 	@Nested
-	class TestGetFormData {
+	class TestGetResponsibleHandler {
 
-		private XtaMessage message;
-		private XdomeaMessageData classification;
+		@Mock
+		private XtaMessageMetaData messageMetaData;
 
-		@Captor
-		private ArgumentCaptor<XtaMessageMetaData> messageMetaDataCaptor;
-
-		@Captor
-		private ArgumentCaptor<XdomeaMessageData>  classificationCaptor;
+		@DisplayName("should return first responsible handler")
+		@Test
+		void shouldReturnHandlerIfResponsible() {
+			when(messageHandler1.isResponsible(messageMetaData)).thenReturn(true);
+			when(xtaMessageHandlers.stream()).thenReturn(Stream.of(messageHandler1, messageHandler2));
 
-		@BeforeEach
-		void init() {
-			message = XtaMessageTestFactory.create();
-			when(remoteService.getMessage(any(XtaMessageId.class))).thenReturn(message);
+			var result = service.getResponsibleHandler(messageMetaData);
 
-			classification = XdomeaMessageDataTestFactory.create();
-			var incomingFiles = List.of(IncomingFileTestFactory.create(), IncomingFileTestFactory.create());
-			when(incomingFilesMapper.toIncomingFiles(message.getMessageFiles())).thenReturn(incomingFiles);
-			classification = XdomeaMessageDataTestFactory.create();
-			when(xdomeaMessageDataMapper.mapIncomingFilesToXdomeaMessageData(incomingFiles)).thenReturn(classification);
+			assertThat(result).contains(messageHandler1);
 		}
 
-		@Test
-		void shouldCallRemoteService() {
-			service.getFormData(XtaMessageMetaDataTestFactory.create());
-
-			verify(remoteService).getMessage(XtaMessageTestFactory.MESSAGE_ID);
+		@DisplayName("with no handler responsible")
+		@Nested
+		class TestWithNoHandlerResponsible {
+			private static final String UNKONWN_MESSAGE_TYPE = "UNKONWN_MESSAGE_TYPE";
+
+			@BeforeEach
+			void mock() {
+				when(messageHandler1.isResponsible(messageMetaData)).thenReturn(false);
+				when(messageHandler2.isResponsible(messageMetaData)).thenReturn(false);
+				when(xtaMessageHandlers.stream()).thenReturn(Stream.of(messageHandler1, messageHandler2));
+				when(messageMetaData.getMessageType()).thenReturn(UNKONWN_MESSAGE_TYPE);
+				doNothing().when(service).logWarningForUnsupportedMessageType(UNKONWN_MESSAGE_TYPE);
+			}
+
+			@DisplayName("should return empty")
+			@Test
+			void shouldReturnEmptyIfNoHandlerResponsible() {
+				var result = service.getResponsibleHandler(messageMetaData);
+
+				assertThat(result).isEmpty();
+			}
+
+			@DisplayName("should log warning")
+			@Test
+			void shouldLogWarningIfNoHandlerResponsible() {
+				service.getResponsibleHandler(messageMetaData);
+
+				verify(service).logWarningForUnsupportedMessageType(UNKONWN_MESSAGE_TYPE);
+			}
 		}
+	}
 
-		@Test
-		void shouldCallMapper() {
-			service.getFormData(XtaMessageMetaDataTestFactory.create());
-
-			verify(mapper).toFormData(any(), any(), eq(vorgangNummerSupplier));
-		}
+	@DisplayName("get form data")
+	@Nested
+	class TestGetFormData {
 
-		@Test
-		void shouldHaveMetaData() {
-			XtaMessageMetaData metaData = XtaMessageMetaDataTestFactory.create();
+		@Mock
+		private XtaMessage msg;
 
-			service.getFormData(metaData);
+		@Mock
+		private List<IncomingFile> incomingFiles;
 
-			verify(mapper).toFormData(classificationCaptor.capture(), messageMetaDataCaptor.capture(), eq(vorgangNummerSupplier));
-			assertThat(messageMetaDataCaptor.getValue()).isEqualTo(metaData);
-			assertThat(classificationCaptor.getValue()).isEqualTo(classification);
-		}
+		@Mock
+		private List<XtaFile> xtaFiles;
 
+		@DisplayName("should return form data")
 		@Test
-		void shouldReturnMappedResult() {
-			var mapped = FormDataTestFactory.create();
-			when(mapper.toFormData(any(), any(), eq(vorgangNummerSupplier))).thenReturn(mapped);
+		void shouldReturnFormData() {
+			var metaData = XtaMessageMetaDataTestFactory.create();
+			when(remoteService.getMessage(metaData.getMessageId())).thenReturn(msg);
+			when(msg.getMessageFiles()).thenReturn(xtaFiles);
+			when(incomingFilesMapper.toIncomingFiles(xtaFiles)).thenReturn(incomingFiles);
+			when(messageHandler1.getFormData(metaData, incomingFiles)).thenReturn(formData);
 
-			var result = service.getFormData(XtaMessageMetaDataTestFactory.create());
+			var result = service.getFormData(metaData, messageHandler1);
 
-			assertThat(result).isSameAs(mapped);
+			assertThat(result).isEqualTo(formData);
 		}
 	}