From c30dcef4c3d87f3995a622c330abd915a6c70267 Mon Sep 17 00:00:00 2001
From: latlon team <info@lat-lon.de>
Date: Tue, 1 Oct 2024 10:18:40 +0000
Subject: [PATCH] Code drop

- XPLANBOX-3349 - set routing keys for import events, updated ManagerPublicEventsIT (6f9eca9e7)
- XPLANBOX-3349 - implement ValidationProcessListener to send rabbitmq events (dce8f1419)
- fixed typo in log (4c9d6bf64)
- XPLANBOX-3349 - added ValidationProcessListener, send validation status to listener (5e9dd18b1)
- XPLANBOX-3349 - added EventTypes, added valid and error (c89226e05)

Co-authored-by: Lyn Elisa Goltz <goltz@lat-lon.de>

Dropped from commit: ae6d7358ac20c2b171e2e410a4710f5c213470ab
---
 .../commons/handler/AbstractAsyncWrapper.java |  2 +-
 .../core/validator/events/EventSender.java    |  2 +-
 .../validator/events/RabbitEventSender.java   | 18 ++--
 .../events/v1/XPlanPublicV1Event.java         | 77 ++++++++++++++---
 .../events/v1/XPlanPublicV1EventTest.java     | 16 ++--
 .../xplan/validator/XPlanGmlValidation.java   | 17 +++-
 .../xplan/validator/XPlanValidator.java       | 85 +++++++++++++------
 .../InactiveValidationProcessListener.java    | 48 +++++++++++
 .../listener/ValidationProcessListener.java   | 25 ++++++
 .../validator/XPlanGmlValidationTest.java     |  6 +-
 .../xplan/validator/XPlanValidatorTest.java   | 18 +++-
 .../geometric/GeometricValidatorImplTest.java |  6 +-
 ...rameterizedGeometricValidatorImplTest.java |  6 +-
 .../planinfo/PlanInfoParserTest.java          |  9 +-
 .../api/manager/executor/PlanImporter.java    |  9 +-
 .../api/manager/handler/PlanHandler.java      |  4 +-
 .../manager/messagingrabbitmq/Receiver.java   |  4 +-
 .../xplanbox/api/manager/v2/PlanApi2.java     |  2 +-
 .../manager/executor/PlanImporterTest.java    |  8 +-
 .../de/latlon/xplanbox/tests/TestConfig.java  |  2 +-
 .../rabbit/manager/ManagerPublicEventsIT.java | 68 +++++++++++----
 .../validator/ValidationPublicEventsIT.java   | 68 ++++++++++-----
 .../api/validator/v2/ValidateApi2.java        |  2 +-
 .../validator/executor/PlanValidator.java     | 85 ++++++++++---------
 .../executor/config/ApplicationContext.java   |  7 +-
 .../executor/handler/ValidationHandler.java   | 10 +--
 .../EventValidationProcessListener.java       | 82 ++++++++++++++++++
 .../executor/messagingrabbitmq/Receiver.java  | 12 +--
 .../validator/executor/PlanValidatorTest.java | 32 +++++--
 .../handler/ValidationHandlerTest.java        |  2 +-
 30 files changed, 544 insertions(+), 188 deletions(-)
 create mode 100644 xplan-core/xplan-core-validator/src/main/java/de/latlon/xplan/validator/listener/InactiveValidationProcessListener.java
 create mode 100644 xplan-core/xplan-core-validator/src/main/java/de/latlon/xplan/validator/listener/ValidationProcessListener.java
 create mode 100644 xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/listener/EventValidationProcessListener.java

diff --git a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/handler/AbstractAsyncWrapper.java b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/handler/AbstractAsyncWrapper.java
index ff0b4eb82..75c8a1f14 100644
--- a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/handler/AbstractAsyncWrapper.java
+++ b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/handler/AbstractAsyncWrapper.java
@@ -28,7 +28,7 @@ public abstract class AbstractAsyncWrapper {
 	}
 
 	public boolean sendEvent(ValidationRequestedEvent event) throws AsyncTimeout {
-		eventSender.sendEvent(event);
+		eventSender.sendPrivateEvent(event);
 
 		String uuid = event.getUuid();
 		LOG.info("Event sent. Waiting for processing of {}", uuid);
diff --git a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/EventSender.java b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/EventSender.java
index f9bee85f9..56d448f6b 100644
--- a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/EventSender.java
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/EventSender.java
@@ -26,7 +26,7 @@ package de.latlon.core.validator.events;
  */
 public interface EventSender {
 
-	void sendEvent(XPlanPrivateEvent e);
+	void sendPrivateEvent(XPlanPrivateEvent e);
 
 	void sendPublicEvent(XPlanPublicEvent event, String routingKeySuffix);
 
diff --git a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitEventSender.java b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitEventSender.java
index d5ba61e74..83fef8447 100644
--- a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitEventSender.java
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitEventSender.java
@@ -65,7 +65,7 @@ class RabbitEventSender implements EventSender {
 	}
 
 	@Override
-	public void sendEvent(XPlanPrivateEvent event) {
+	public void sendPrivateEvent(XPlanPrivateEvent event) {
 		if (event instanceof XPlanPrivateTaskEvent) {
 			sendPrivateTaskEvent((XPlanPrivateTaskEvent) event);
 		}
@@ -73,6 +73,14 @@ class RabbitEventSender implements EventSender {
 			sendPrivateTopicEvent((XPlanPrivateTopicEvent) event);
 	}
 
+	@Override
+	public void sendPublicEvent(XPlanPublicEvent event, String routingKeySuffix) {
+		String routingKey = publicTopicRoutingPrefix + routingKeySuffix;
+
+		LOG.info("Sending public event with key >{}<: {}", routingKey, event);
+		rabbitTemplate.convertAndSend(publicTopicExchangeName, routingKey, event);
+	}
+
 	private void sendPrivateTaskEvent(XPlanPrivateTaskEvent event) {
 		String workQueueName = taskClass2QueueName.get(event.getClass());
 		if (workQueueName == null) {
@@ -91,12 +99,4 @@ class RabbitEventSender implements EventSender {
 		rabbitTemplate.convertAndSend(privateTopicExchangeName, routingKey, event);
 	}
 
-	@Override
-	public void sendPublicEvent(XPlanPublicEvent event, String routingKeySuffix) {
-		String routingKey = publicTopicRoutingPrefix + routingKeySuffix;
-
-		LOG.info("Sending public event with key >{}<: {}", routingKey, event);
-		rabbitTemplate.convertAndSend(publicTopicExchangeName, routingKey, event);
-	}
-
 }
diff --git a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/v1/XPlanPublicV1Event.java b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/v1/XPlanPublicV1Event.java
index c295c1af3..d4e6cb97b 100644
--- a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/v1/XPlanPublicV1Event.java
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/v1/XPlanPublicV1Event.java
@@ -14,26 +14,75 @@ public class XPlanPublicV1Event implements XPlanPublicEvent {
 
 	public enum EventType {
 
-		VALIDATION_STARTED, VALIDATION_FINISHED, IMPORT_STARTED, IMPORT_FINISHED
+		VALIDATION_STARTED("validation"),
+
+		SYNTACTIC_VALIDATION_STARTED("validation.syntaktisch"),
+
+		SYNTACTIC_VALIDATION_FINISHED("validation.syntaktisch"),
+
+		GEOMETRIC_VALIDATION_STARTED("validation.geometrisch"),
+
+		GEOMETRIC_VALIDATION_FINISHED("validation.geometrisch"),
+
+		SEMANTIC_VALIDATION_STARTED("validation.semantisch"),
+
+		SEMANTIC_VALIDATION_FINISHED("validation.semantisch"),
+
+		PROFILE_VALIDATION_STARTED("validation.profile."),
+
+		PROFILE_VALIDATION_FINISHED("validation.profile."),
+
+		VALIDATION_FINISHED("validation"),
+
+		VALIDATION_FAILED("validation"),
+
+		IMPORT_STARTED("import"),
+
+		IMPORT_FINISHED("import"),
+
+		IMPORT_FAILED("import");
+
+		private final String routingKeySuffix;
+
+		EventType(String routingKeySuffix) {
+			this.routingKeySuffix = routingKeySuffix;
+		}
+
+		public String routingKeySuffix() {
+			return routingKeySuffix;
+		}
 
 	}
 
-	private String apiVersion = "1.0";
+	private final String apiVersion = "1.0";
 
 	private EventType eventType;
 
 	private String uuid;
 
-	private String message;
+	private Boolean valid;
+
+	private String error;
 
 	public XPlanPublicV1Event() {
 
 	}
 
-	public XPlanPublicV1Event(EventType eventType, String uuid, String message) {
+	public XPlanPublicV1Event(EventType eventType, String uuid) {
+		this.eventType = eventType;
+		this.uuid = uuid;
+	}
+
+	public XPlanPublicV1Event(EventType eventType, String uuid, Boolean valid) {
 		this.eventType = eventType;
 		this.uuid = uuid;
-		this.message = message;
+		this.valid = valid;
+	}
+
+	public XPlanPublicV1Event(EventType eventType, String uuid, String error) {
+		this.eventType = eventType;
+		this.uuid = uuid;
+		this.error = error;
 	}
 
 	public String getApiVersion() {
@@ -44,17 +93,21 @@ public class XPlanPublicV1Event implements XPlanPublicEvent {
 		return eventType;
 	}
 
-	public String getMessage() {
-		return message;
-	}
-
 	public String getUuid() {
 		return uuid;
 	}
 
+	public Boolean getValid() {
+		return valid;
+	}
+
+	public String getError() {
+		return error;
+	}
+
 	@Override
 	public int hashCode() {
-		return Objects.hash(apiVersion, eventType, message, uuid);
+		return Objects.hash(apiVersion, eventType, uuid);
 	}
 
 	@Override
@@ -67,12 +120,12 @@ public class XPlanPublicV1Event implements XPlanPublicEvent {
 			return false;
 		XPlanPublicV1Event other = (XPlanPublicV1Event) obj;
 		return Objects.equals(apiVersion, other.apiVersion) && eventType == other.eventType
-				&& Objects.equals(message, other.message) && Objects.equals(uuid, other.uuid);
+				&& Objects.equals(uuid, other.uuid);
 	}
 
 	@Override
 	public String toString() {
-		return "XPlanboxPublicV1Event(" + eventType + ", " + uuid + ", " + message + ")";
+		return "XPlanboxPublicV1Event(" + eventType + ", " + uuid + ")";
 	}
 
 }
diff --git a/xplan-core/xplan-core-validator-events/src/test/java/de/latlon/core/validator/events/v1/XPlanPublicV1EventTest.java b/xplan-core/xplan-core-validator-events/src/test/java/de/latlon/core/validator/events/v1/XPlanPublicV1EventTest.java
index 1d698f880..f8d07c401 100644
--- a/xplan-core/xplan-core-validator-events/src/test/java/de/latlon/core/validator/events/v1/XPlanPublicV1EventTest.java
+++ b/xplan-core/xplan-core-validator-events/src/test/java/de/latlon/core/validator/events/v1/XPlanPublicV1EventTest.java
@@ -14,48 +14,48 @@ class XPlanPublicV1EventTest {
 
 	@Test
 	void jsonSerializeValidationStarted() throws Exception {
-		XPlanPublicV1Event event = new XPlanPublicV1Event(EventType.VALIDATION_STARTED, "uuid1", "start validation");
+		XPlanPublicV1Event event = new XPlanPublicV1Event(EventType.VALIDATION_STARTED, "uuid1");
 
 		ObjectMapper mapper = new ObjectMapper();
 		String json = mapper.writeValueAsString(event);
 
-		String expected = "{\"apiVersion\":\"1.0\",\"eventType\":\"VALIDATION_STARTED\",\"uuid\":\"uuid1\",\"message\":\"start validation\"}";
+		String expected = "{\"apiVersion\":\"1.0\",\"eventType\":\"VALIDATION_STARTED\",\"uuid\":\"uuid1\",\"valid\":null,\"error\":null}";
 
 		assertThat(json).isEqualTo(expected);
 	}
 
 	@Test
 	void jsonSerializeValidationFinished() throws Exception {
-		XPlanPublicV1Event event = new XPlanPublicV1Event(EventType.VALIDATION_FINISHED, "uuid1", "end validation");
+		XPlanPublicV1Event event = new XPlanPublicV1Event(EventType.VALIDATION_FINISHED, "uuid1", true);
 
 		ObjectMapper mapper = new ObjectMapper();
 		String json = mapper.writeValueAsString(event);
 
-		String expected = "{\"apiVersion\":\"1.0\",\"eventType\":\"VALIDATION_FINISHED\",\"uuid\":\"uuid1\",\"message\":\"end validation\"}";
+		String expected = "{\"apiVersion\":\"1.0\",\"eventType\":\"VALIDATION_FINISHED\",\"uuid\":\"uuid1\",\"valid\":true,\"error\":null}";
 
 		assertThat(json).isEqualTo(expected);
 	}
 
 	@Test
 	void jsonSerializeImportStart() throws Exception {
-		XPlanPublicV1Event event = new XPlanPublicV1Event(EventType.IMPORT_STARTED, "uuid1", "start import");
+		XPlanPublicV1Event event = new XPlanPublicV1Event(EventType.IMPORT_STARTED, "uuid1");
 
 		ObjectMapper mapper = new ObjectMapper();
 		String json = mapper.writeValueAsString(event);
 
-		String expected = "{\"apiVersion\":\"1.0\",\"eventType\":\"IMPORT_STARTED\",\"uuid\":\"uuid1\",\"message\":\"start import\"}";
+		String expected = "{\"apiVersion\":\"1.0\",\"eventType\":\"IMPORT_STARTED\",\"uuid\":\"uuid1\",\"valid\":null,\"error\":null}";
 
 		assertThat(json).isEqualTo(expected);
 	}
 
 	@Test
 	void jsonSerializeImportFinished() throws Exception {
-		XPlanPublicV1Event event = new XPlanPublicV1Event(EventType.IMPORT_FINISHED, "uuid1", "end import");
+		XPlanPublicV1Event event = new XPlanPublicV1Event(EventType.IMPORT_FINISHED, "uuid1");
 
 		ObjectMapper mapper = new ObjectMapper();
 		String json = mapper.writeValueAsString(event);
 
-		String expected = "{\"apiVersion\":\"1.0\",\"eventType\":\"IMPORT_FINISHED\",\"uuid\":\"uuid1\",\"message\":\"end import\"}";
+		String expected = "{\"apiVersion\":\"1.0\",\"eventType\":\"IMPORT_FINISHED\",\"uuid\":\"uuid1\",\"valid\":null,\"error\":null}";
 
 		assertThat(json).isEqualTo(expected);
 	}
diff --git a/xplan-core/xplan-core-validator/src/main/java/de/latlon/xplan/validator/XPlanGmlValidation.java b/xplan-core/xplan-core-validator/src/main/java/de/latlon/xplan/validator/XPlanGmlValidation.java
index 3df90d774..7ac66b805 100644
--- a/xplan-core/xplan-core-validator/src/main/java/de/latlon/xplan/validator/XPlanGmlValidation.java
+++ b/xplan-core/xplan-core-validator/src/main/java/de/latlon/xplan/validator/XPlanGmlValidation.java
@@ -12,6 +12,7 @@ import de.latlon.xplan.commons.feature.XPlanGmlParser;
 import de.latlon.xplan.commons.feature.XPlanGmlParserBuilder;
 import de.latlon.xplan.validator.geometric.GeometricValidator;
 import de.latlon.xplan.validator.geometric.report.GeometricValidatorResult;
+import de.latlon.xplan.validator.listener.ValidationProcessListener;
 import de.latlon.xplan.validator.planinfo.PlanInfoParser;
 import de.latlon.xplan.validator.planinfo.PlanInfoReport;
 import de.latlon.xplan.validator.report.ValidatorReport;
@@ -45,23 +46,27 @@ public class XPlanGmlValidation {
 
 	private PlanInfoReport planInfoReport;
 
+	private final ValidationProcessListener validationProcessListener;
+
 	public XPlanGmlValidation(GeometricValidator geometricValidator, PlanInfoParser planInfoParser,
-			XPlanArchive archive, ValidationSettings validationSettings) {
+			XPlanArchive archive, ValidationSettings validationSettings,
+			ValidationProcessListener validationProcessListener) {
 		this.geometricValidator = geometricValidator;
 		this.planInfoParser = planInfoParser;
 		this.archive = archive;
 		this.validationSettings = validationSettings;
+		this.validationProcessListener = validationProcessListener;
 		this.gmlParserBuilder = XPlanGmlParserBuilder.newBuilder();
 	}
 
-	public void executeGmlValidation(ValidatorReport report) throws ValidatorException {
+	public void executeGmlValidation(String uuid, ValidatorReport report) throws ValidatorException {
 		boolean skipGeometric = !validationSettings.getValidationTypes().contains(GEOMETRIC);
 		// prepare
 		prepareGmlValidation(skipGeometric);
 		// build
 		buildGmlValidation(skipGeometric);
 		// validate
-		parseGmlValidation(report, skipGeometric);
+		parseGmlValidation(uuid, report, skipGeometric);
 	}
 
 	public XPlanGmlParserBuilder getGmlParserBuilder() {
@@ -115,7 +120,8 @@ public class XPlanGmlValidation {
 			geometricValidator.afterParserBuild(this);
 	}
 
-	private void parseGmlValidation(ValidatorReport report, boolean skipGeometric) throws ValidatorException {
+	private void parseGmlValidation(String uuid, ValidatorReport report, boolean skipGeometric)
+			throws ValidatorException {
 		parse();
 		this.planInfoReport = planInfoParser.parsePlanInfo(this);
 		report.setPlanInfoReport(planInfoReport);
@@ -126,10 +132,13 @@ public class XPlanGmlValidation {
 					.geometricValidatorResult(new GeometricValidatorResult(SKIPPED)));
 		}
 		else {
+			validationProcessListener.validationPartStarted(uuid, GEOMETRIC);
 			Map<String, GeometricValidatorResult> validatorResult = geometricValidator.validateGeometry(this);
 			report.getPlanInfoReport()
 				.getPlanInfos()
 				.forEach((planGmlId, planInfo) -> planInfo.geometricValidatorResult(validatorResult.get(planGmlId)));
+			validationProcessListener.validationPartFinished(uuid, GEOMETRIC,
+					validatorResult.values().stream().allMatch(GeometricValidatorResult::isValid));
 		}
 	}
 
diff --git a/xplan-core/xplan-core-validator/src/main/java/de/latlon/xplan/validator/XPlanValidator.java b/xplan-core/xplan-core-validator/src/main/java/de/latlon/xplan/validator/XPlanValidator.java
index 5f00fb609..fc300df11 100644
--- a/xplan-core/xplan-core-validator/src/main/java/de/latlon/xplan/validator/XPlanValidator.java
+++ b/xplan-core/xplan-core-validator/src/main/java/de/latlon/xplan/validator/XPlanValidator.java
@@ -24,6 +24,7 @@ import static de.latlon.xplan.validator.report.SkipCode.SKIPPED;
 import static de.latlon.xplan.validator.report.SkipCode.SYNTAX_ERRORS;
 import static de.latlon.xplan.validator.report.SkipCode.UNSUPPORTED;
 import static de.latlon.xplan.validator.web.shared.ValidationType.SEMANTIC;
+import static de.latlon.xplan.validator.web.shared.ValidationType.SYNTACTIC;
 
 import java.io.File;
 import java.io.IOException;
@@ -33,6 +34,7 @@ import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 import java.util.Optional;
+import java.util.UUID;
 import java.util.stream.Collectors;
 
 import de.latlon.xplan.commons.archive.SemanticValidableXPlanArchive;
@@ -40,6 +42,8 @@ import de.latlon.xplan.commons.archive.XPlanArchive;
 import de.latlon.xplan.commons.archive.XPlanArchiveCreator;
 import de.latlon.xplan.commons.feature.XPlanFeatureCollection;
 import de.latlon.xplan.validator.geometric.GeometricValidator;
+import de.latlon.xplan.validator.listener.InactiveValidationProcessListener;
+import de.latlon.xplan.validator.listener.ValidationProcessListener;
 import de.latlon.xplan.validator.planinfo.PlanInfo;
 import de.latlon.xplan.validator.planinfo.PlanInfoParser;
 import de.latlon.xplan.validator.planinfo.PlanInfoReport;
@@ -85,15 +89,26 @@ public class XPlanValidator {
 
 	private final XPlanArchiveCreator archiveCreator = new XPlanArchiveCreator();
 
+	private final ValidationProcessListener validationProcessListener;
+
 	public XPlanValidator(GeometricValidator geometricValidator, SyntacticValidator syntacticValidator,
 			SemanticValidator semanticValidator, List<SemanticProfileValidator> semanticProfileValidators,
 			ReportArchiveGenerator reportArchiveGenerator, PlanInfoParser planInfoParser) {
+		this(geometricValidator, syntacticValidator, semanticValidator, semanticProfileValidators,
+				reportArchiveGenerator, planInfoParser, new InactiveValidationProcessListener());
+	}
+
+	public XPlanValidator(GeometricValidator geometricValidator, SyntacticValidator syntacticValidator,
+			SemanticValidator semanticValidator, List<SemanticProfileValidator> semanticProfileValidators,
+			ReportArchiveGenerator reportArchiveGenerator, PlanInfoParser planInfoParser,
+			ValidationProcessListener validationProcessListener) {
 		this.geometricValidator = geometricValidator;
 		this.syntacticValidator = syntacticValidator;
 		this.semanticValidator = semanticValidator;
 		this.semanticProfileValidators = semanticProfileValidators;
 		this.reportArchiveGenerator = reportArchiveGenerator;
 		this.planInfoParser = planInfoParser;
+		this.validationProcessListener = validationProcessListener;
 	}
 
 	/**
@@ -109,7 +124,7 @@ public class XPlanValidator {
 	public ValidatorReport validate(ValidationSettings validationSettings, File planArchive, String archiveName)
 			throws ValidatorException, IOException, ReportGenerationException {
 		XPlanArchive archive = archiveCreator.createXPlanArchive(planArchive);
-		ValidatorReport report = validate(validationSettings, archive, archiveName);
+		ValidatorReport report = validate(UUID.randomUUID().toString(), validationSettings, archive, archiveName);
 		writeReport(report);
 		LOG.info("Archiv mit Validierungsergebnissen wird erstellt.");
 		Path validationReportDirectory = createZipArchive(validationSettings, report);
@@ -129,7 +144,7 @@ public class XPlanValidator {
 	public ValidatorReport validateNotWriteReport(ValidationSettings validationSettings, File planArchive,
 			String archiveName) throws ValidatorException, IOException {
 		XPlanArchive archive = archiveCreator.createXPlanArchive(planArchive);
-		return validateNotWriteReport(validationSettings, archive, archiveName);
+		return validateNotWriteReport(null, validationSettings, archive, archiveName);
 	}
 
 	/**
@@ -139,9 +154,9 @@ public class XPlanValidator {
 	 * @return <link>ValidatorReport</link>
 	 * @throws ValidatorException
 	 */
-	public ValidatorReport validateNotWriteReport(ValidationSettings validationSettings, XPlanArchive planArchive,
-			String archiveName) throws ValidatorException {
-		ValidatorReport validationReport = validate(validationSettings, planArchive, archiveName);
+	public ValidatorReport validateNotWriteReport(String uuid, ValidationSettings validationSettings,
+			XPlanArchive planArchive, String archiveName) throws ValidatorException {
+		ValidatorReport validationReport = validate(uuid, validationSettings, planArchive, archiveName);
 		validationReport.setHasMultipleXPlanElements(planArchive.hasMultipleXPlanElements());
 		return validationReport;
 	}
@@ -162,30 +177,40 @@ public class XPlanValidator {
 		}
 	}
 
-	private ValidatorReport validate(ValidationSettings validationSettings, XPlanArchive archive, String archiveName)
-			throws ValidatorException {
-		List<SemanticValidationOptions> semanticValidationOptions = extractSemanticValidationOptions(
-				validationSettings);
+	private ValidatorReport validate(String uuid, ValidationSettings validationSettings, XPlanArchive archive,
+			String archiveName) throws ValidatorException {
+		try {
+			validationProcessListener.validationStarted(uuid);
+			List<SemanticValidationOptions> semanticValidationOptions = extractSemanticValidationOptions(
+					validationSettings);
+
+			ValidatorReport report = new ValidatorReport();
+			report.setValidationName(validationSettings.getValidationName());
+			report.setArchiveName(archiveName);
+			report.setDate(new Date());
+
+			List<ValidationType> validationType = getValidationType(validationSettings);
+			validationProcessListener.validationPartStarted(uuid, SYNTACTIC);
+			SyntacticValidatorResult syntacticValidatorResult = validateSyntactic(archive, report);
+			validationProcessListener.validationPartFinished(uuid, SYNTACTIC, syntacticValidatorResult.isValid());
+			if (!syntacticValidatorResult.isValid()) {
+				report.setPlanInfoReport(new PlanInfoReport().skipCode(SYNTAX_ERRORS));
+				return report;
+			}
 
-		ValidatorReport report = new ValidatorReport();
-		report.setValidationName(validationSettings.getValidationName());
-		report.setArchiveName(archiveName);
-		report.setDate(new Date());
+			XPlanGmlValidation xPlanGmlValidation = new XPlanGmlValidation(geometricValidator, planInfoParser, archive,
+					validationSettings, validationProcessListener);
+			xPlanGmlValidation.executeGmlValidation(uuid, report);
 
-		List<ValidationType> validationType = getValidationType(validationSettings);
-		SyntacticValidatorResult syntacticValidatorResult = validateSyntactic(archive, report);
-		if (!syntacticValidatorResult.isValid()) {
-			report.setPlanInfoReport(new PlanInfoReport().skipCode(SYNTAX_ERRORS));
+			valideSemanticAndProfiles(uuid, validationSettings, archive, xPlanGmlValidation, semanticValidationOptions,
+					validationType, report);
+			validationProcessListener.validationFinished(uuid, report.isValid());
 			return report;
 		}
-
-		XPlanGmlValidation xPlanGmlValidation = new XPlanGmlValidation(geometricValidator, planInfoParser, archive,
-				validationSettings);
-		xPlanGmlValidation.executeGmlValidation(report);
-
-		valideSemanticAndProfiles(validationSettings, archive, xPlanGmlValidation, semanticValidationOptions,
-				validationType, report);
-		return report;
+		catch (ValidatorException e) {
+			validationProcessListener.validationFailed(uuid, e.getMessage());
+			throw e;
+		}
 	}
 
 	private SyntacticValidatorResult validateSyntactic(XPlanArchive archive, ValidatorReport report) {
@@ -195,7 +220,7 @@ public class XPlanValidator {
 
 	}
 
-	private void valideSemanticAndProfiles(ValidationSettings validationSettings, XPlanArchive archive,
+	private void valideSemanticAndProfiles(String uuid, ValidationSettings validationSettings, XPlanArchive archive,
 			XPlanGmlValidation gmlValidation, List<SemanticValidationOptions> semanticValidationOptions,
 			List<ValidationType> validationTypes, ValidatorReport report) throws ValidatorException {
 		boolean multiplePlansReferencesWithMultiplePlans = archive.hasMultipleXPlanElements()
@@ -216,24 +241,28 @@ public class XPlanValidator {
 			else if (!validationTypes.contains(SEMANTIC))
 				planInfo.semanticValidatorResult(new SemanticValidatorResult(SKIPPED));
 			else {
+				validationProcessListener.validationPartStarted(uuid, SEMANTIC);
 				SemanticValidatorResult semanticallyResult = validateSemanticallyAndWriteResult(semanticValidator,
 						instanceAsArchive, semanticValidationOptions);
 				planInfo.semanticValidatorResult(semanticallyResult);
+				validationProcessListener.validationPartFinished(uuid, SEMANTIC, semanticallyResult.isValid());
 			}
-			validateSemanticProfiles(instanceAsArchive, profiles, planInfo);
+			validateSemanticProfiles(uuid, instanceAsArchive, profiles, planInfo);
 		}
 	}
 
-	private void validateSemanticProfiles(SemanticValidableXPlanArchive archive, List<String> profiles,
+	private void validateSemanticProfiles(String uuid, SemanticValidableXPlanArchive archive, List<String> profiles,
 			PlanInfo planInfo) throws ValidatorException {
 		for (String profileId : profiles) {
 			Optional<SemanticProfileValidator> profileValidator = semanticProfileValidators.stream()
 				.filter(semanticProfileValidator -> semanticProfileValidator.getId().equals(profileId))
 				.findFirst();
 			if (profileValidator.isPresent()) {
+				validationProcessListener.validationProfileStarted(uuid, profileId);
 				SemanticValidatorResult semanticValidatorResult = validateSemanticallyAndWriteResult(
 						profileValidator.get(), archive, Collections.emptyList());
 				planInfo.addSemanticProfileValidatorResults(semanticValidatorResult);
+				validationProcessListener.validationProfileFinished(uuid, profileId, semanticValidatorResult.isValid());
 			}
 			else {
 				throw new ValidatorException("Profile with id " + profileId + " does not exist");
diff --git a/xplan-core/xplan-core-validator/src/main/java/de/latlon/xplan/validator/listener/InactiveValidationProcessListener.java b/xplan-core/xplan-core-validator/src/main/java/de/latlon/xplan/validator/listener/InactiveValidationProcessListener.java
new file mode 100644
index 000000000..66d9351ba
--- /dev/null
+++ b/xplan-core/xplan-core-validator/src/main/java/de/latlon/xplan/validator/listener/InactiveValidationProcessListener.java
@@ -0,0 +1,48 @@
+package de.latlon.xplan.validator.listener;
+
+import de.latlon.xplan.validator.web.shared.ValidationType;
+
+/**
+ * Implements {@link ValidationProcessListener with empty methods
+ *
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+public class InactiveValidationProcessListener implements ValidationProcessListener {
+
+	@Override
+	public void validationStarted(String uuid) {
+
+	}
+
+	@Override
+	public void validationPartStarted(String uuid, ValidationType validationType) {
+
+	}
+
+	@Override
+	public void validationPartFinished(String uuid, ValidationType validationType, Boolean isValid) {
+
+	}
+
+	@Override
+	public void validationProfileStarted(String uuid, String profileId) {
+
+	}
+
+	@Override
+	public void validationProfileFinished(String uuid, String profileId, Boolean isValid) {
+
+	}
+
+	@Override
+	public void validationFinished(String uuid, Boolean valid) {
+
+	}
+
+	@Override
+	public void validationFailed(String uuid, String error) {
+
+	}
+
+}
diff --git a/xplan-core/xplan-core-validator/src/main/java/de/latlon/xplan/validator/listener/ValidationProcessListener.java b/xplan-core/xplan-core-validator/src/main/java/de/latlon/xplan/validator/listener/ValidationProcessListener.java
new file mode 100644
index 000000000..524be4a4b
--- /dev/null
+++ b/xplan-core/xplan-core-validator/src/main/java/de/latlon/xplan/validator/listener/ValidationProcessListener.java
@@ -0,0 +1,25 @@
+package de.latlon.xplan.validator.listener;
+
+import de.latlon.xplan.validator.web.shared.ValidationType;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+public interface ValidationProcessListener {
+
+	void validationStarted(String uuid);
+
+	void validationPartStarted(String uuid, ValidationType validationType);
+
+	void validationPartFinished(String uuid, ValidationType validationType, Boolean isValid);
+
+	void validationProfileStarted(String uuid, String profileId);
+
+	void validationProfileFinished(String uuid, String profileId, Boolean isValid);
+
+	void validationFinished(String uuid, Boolean isValid);
+
+	void validationFailed(String uuid, String error);
+
+}
diff --git a/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/XPlanGmlValidationTest.java b/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/XPlanGmlValidationTest.java
index a36efd802..2a9ad3939 100644
--- a/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/XPlanGmlValidationTest.java
+++ b/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/XPlanGmlValidationTest.java
@@ -18,6 +18,7 @@ import de.latlon.xplan.validator.geometric.GeometricValidatorImpl;
 import de.latlon.xplan.validator.geometric.report.GeometricValidatorResult;
 import de.latlon.xplan.validator.geometric.result.GeometricValidationFinding;
 import de.latlon.xplan.validator.geometric.result.GeometricValidationRule;
+import de.latlon.xplan.validator.listener.InactiveValidationProcessListener;
 import de.latlon.xplan.validator.planinfo.PlanInfoParser;
 import de.latlon.xplan.validator.report.ValidatorReport;
 import de.latlon.xplan.validator.web.shared.ValidationSettings;
@@ -36,9 +37,10 @@ public class XPlanGmlValidationTest {
 		ValidationSettings validationSettings = new ValidationSettings("test", List.of(SYNTACTIC, SEMANTIC, GEOMETRIC),
 				SKIP_OPTIONS);
 		XPlanGmlValidation xPlanGmlValidation = new XPlanGmlValidation(new GeometricValidatorImpl(),
-				new PlanInfoParser(Optional.empty()), archive, validationSettings);
+				new PlanInfoParser(Optional.empty()), archive, validationSettings,
+				new InactiveValidationProcessListener());
 		ValidatorReport report = new ValidatorReport();
-		xPlanGmlValidation.executeGmlValidation(report);
+		xPlanGmlValidation.executeGmlValidation("uuid", report);
 
 		GeometricValidatorResult geometricReport = report.getPlanInfoReport()
 			.getPlanInfos()
diff --git a/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/XPlanValidatorTest.java b/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/XPlanValidatorTest.java
index e16c554f4..c01d59124 100644
--- a/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/XPlanValidatorTest.java
+++ b/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/XPlanValidatorTest.java
@@ -28,6 +28,9 @@ import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
@@ -55,6 +58,7 @@ import de.latlon.xplan.commons.feature.XPlanGmlParserBuilder;
 import de.latlon.xplan.validator.geometric.GeometricValidator;
 import de.latlon.xplan.validator.geometric.GeometricValidatorImpl;
 import de.latlon.xplan.validator.geometric.report.GeometricValidatorResult;
+import de.latlon.xplan.validator.listener.ValidationProcessListener;
 import de.latlon.xplan.validator.planinfo.PlanInfo;
 import de.latlon.xplan.validator.planinfo.PlanInfoParser;
 import de.latlon.xplan.validator.report.ReportArchiveGenerator;
@@ -99,6 +103,8 @@ public class XPlanValidatorTest {
 
 	private XPlanGmlParser xPlanGmlParser;
 
+	private ValidationProcessListener validationProcessListener;
+
 	private static File planToValidate;
 
 	@Before
@@ -109,6 +115,7 @@ public class XPlanValidatorTest {
 		synVal = mockSyntacticValidator();
 		synValInvalid = mockSyntacticValidatorWithError();
 		xPlanGmlParser = mockXPlanGmlParser();
+		validationProcessListener = mock(ValidationProcessListener.class);
 	}
 
 	@BeforeClass
@@ -176,6 +183,15 @@ public class XPlanValidatorTest {
 		verify(geoVal, times(1)).validateGeometry(gmlValidation());
 		verify(semVal, times(1)).validateSemantic(semanticValidableXPlanArchive(), list());
 		verifyNoInteractions(xPlanGmlParser);
+
+		verify(validationProcessListener, times(1)).validationStarted(anyString());
+		verify(validationProcessListener, times(1)).validationPartStarted(anyString(), eq(SYNTACTIC));
+		verify(validationProcessListener, times(1)).validationPartFinished(anyString(), eq(SYNTACTIC), anyBoolean());
+		verify(validationProcessListener, times(1)).validationPartStarted(anyString(), eq(SEMANTIC));
+		verify(validationProcessListener, times(1)).validationPartFinished(anyString(), eq(SEMANTIC), anyBoolean());
+		verify(validationProcessListener, times(1)).validationPartStarted(anyString(), eq(GEOMETRIC));
+		verify(validationProcessListener, times(1)).validationPartFinished(anyString(), eq(GEOMETRIC), anyBoolean());
+		verify(validationProcessListener, times(1)).validationFinished(anyString(), anyBoolean());
 	}
 
 	@Test
@@ -389,7 +405,7 @@ public class XPlanValidatorTest {
 			SyntacticValidator synVal, List<SemanticProfileValidator> profileValidators, ValidationSettings settings)
 			throws IOException, ValidatorException, ReportGenerationException {
 		XPlanValidator validator = new XPlanValidator(geomVal, synVal, semVal, profileValidators,
-				mock(ReportArchiveGenerator.class), new PlanInfoParser(Optional.empty()));
+				mock(ReportArchiveGenerator.class), new PlanInfoParser(Optional.empty()), validationProcessListener);
 		return validator.validate(settings, planToValidate, "archiveName");
 	}
 
diff --git a/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/geometric/GeometricValidatorImplTest.java b/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/geometric/GeometricValidatorImplTest.java
index 31a860251..4a42d1ed5 100644
--- a/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/geometric/GeometricValidatorImplTest.java
+++ b/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/geometric/GeometricValidatorImplTest.java
@@ -45,6 +45,7 @@ import de.latlon.xplan.validator.XPlanGmlValidation;
 import de.latlon.xplan.validator.geometric.report.GeometricValidatorResult;
 import de.latlon.xplan.validator.geometric.result.GeometricValidationFinding;
 import de.latlon.xplan.validator.geometric.result.GeometricValidationRule;
+import de.latlon.xplan.validator.listener.InactiveValidationProcessListener;
 import de.latlon.xplan.validator.planinfo.PlanInfoParser;
 import de.latlon.xplan.validator.report.ValidatorReport;
 import de.latlon.xplan.validator.report.ValidatorResult;
@@ -243,9 +244,10 @@ public class GeometricValidatorImplTest {
 				voOptions);
 		GeometricValidatorImpl geometricValidator = new GeometricValidatorImpl();
 		XPlanGmlValidation xPlanGmlValidation = new XPlanGmlValidation(geometricValidator,
-				new PlanInfoParser(Optional.empty()), archive, validationSettings);
+				new PlanInfoParser(Optional.empty()), archive, validationSettings,
+				new InactiveValidationProcessListener());
 		ValidatorReport report = new ValidatorReport();
-		xPlanGmlValidation.executeGmlValidation(report);
+		xPlanGmlValidation.executeGmlValidation("uuid", report);
 		return report.getPlanInfoReport()
 			.getPlanInfos()
 			.values()
diff --git a/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/geometric/ParameterizedGeometricValidatorImplTest.java b/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/geometric/ParameterizedGeometricValidatorImplTest.java
index 9b2e78695..d52857d6d 100644
--- a/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/geometric/ParameterizedGeometricValidatorImplTest.java
+++ b/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/geometric/ParameterizedGeometricValidatorImplTest.java
@@ -37,6 +37,7 @@ import de.latlon.xplan.commons.archive.XPlanArchiveCreator;
 import de.latlon.xplan.validator.ValidatorException;
 import de.latlon.xplan.validator.XPlanGmlValidation;
 import de.latlon.xplan.validator.geometric.report.GeometricValidatorResult;
+import de.latlon.xplan.validator.listener.InactiveValidationProcessListener;
 import de.latlon.xplan.validator.planinfo.PlanInfoParser;
 import de.latlon.xplan.validator.report.ValidatorReport;
 import de.latlon.xplan.validator.report.ValidatorResult;
@@ -101,9 +102,10 @@ public class ParameterizedGeometricValidatorImplTest {
 				SKIP_OPTIONS);
 
 		XPlanGmlValidation xPlanGmlValidation = new XPlanGmlValidation(geometricValidator,
-				new PlanInfoParser(Optional.empty()), archive, validationSettings);
+				new PlanInfoParser(Optional.empty()), archive, validationSettings,
+				new InactiveValidationProcessListener());
 		ValidatorReport report = new ValidatorReport();
-		xPlanGmlValidation.executeGmlValidation(report);
+		xPlanGmlValidation.executeGmlValidation("uuid", report);
 		return report.getPlanInfoReport()
 			.getPlanInfos()
 			.values()
diff --git a/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/planinfo/PlanInfoParserTest.java b/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/planinfo/PlanInfoParserTest.java
index 924582b52..916eefad9 100644
--- a/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/planinfo/PlanInfoParserTest.java
+++ b/xplan-core/xplan-core-validator/src/test/java/de/latlon/xplan/validator/planinfo/PlanInfoParserTest.java
@@ -19,6 +19,7 @@ import de.latlon.xplan.manager.web.shared.RasterEvaluationResult;
 import de.latlon.xplan.validator.ValidatorException;
 import de.latlon.xplan.validator.XPlanGmlValidation;
 import de.latlon.xplan.validator.geometric.GeometricValidatorImpl;
+import de.latlon.xplan.validator.listener.InactiveValidationProcessListener;
 import de.latlon.xplan.validator.report.ValidatorReport;
 import de.latlon.xplan.validator.web.shared.ValidationSettings;
 import de.latlon.xplanbox.core.raster.evaluation.XPlanRasterEvaluation;
@@ -38,8 +39,8 @@ public class PlanInfoParserTest {
 		XPlanArchive archive = new XPlanArchiveCreator().createXPlanArchiveFromZip("test", planToTest);
 
 		XPlanGmlValidation xPlanGmlValidation = new XPlanGmlValidation(new GeometricValidatorImpl(), planInfoParser,
-				archive, new ValidationSettings());
-		xPlanGmlValidation.executeGmlValidation(new ValidatorReport());
+				archive, new ValidationSettings(), new InactiveValidationProcessListener());
+		xPlanGmlValidation.executeGmlValidation("uuid", new ValidatorReport());
 		PlanInfoReport planInfoReport = planInfoParser.parsePlanInfo(xPlanGmlValidation);
 
 		assertEquals(1, planInfoReport.getPlanInfos().size());
@@ -67,8 +68,8 @@ public class PlanInfoParserTest {
 		XPlanArchive archive = new XPlanArchiveCreator().createXPlanArchiveFromGml("test", planToTest);
 
 		XPlanGmlValidation xPlanGmlValidation = new XPlanGmlValidation(new GeometricValidatorImpl(), planInfoParser,
-				archive, new ValidationSettings());
-		xPlanGmlValidation.executeGmlValidation(new ValidatorReport());
+				archive, new ValidationSettings(), new InactiveValidationProcessListener());
+		xPlanGmlValidation.executeGmlValidation("uuid", new ValidatorReport());
 		PlanInfoReport planInfoReport = planInfoParser.parsePlanInfo(xPlanGmlValidation);
 
 		assertEquals(planInfoReport.getPlanInfos().size(), 3);
diff --git a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/executor/PlanImporter.java b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/executor/PlanImporter.java
index 3ec8bd9bd..9c0beb2cc 100644
--- a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/executor/PlanImporter.java
+++ b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/executor/PlanImporter.java
@@ -20,6 +20,7 @@
  */
 package de.latlon.xplanbox.api.manager.executor;
 
+import static de.latlon.core.validator.events.v1.XPlanPublicV1Event.EventType.IMPORT_FINISHED;
 import static de.latlon.core.validator.events.v1.XPlanPublicV1Event.EventType.IMPORT_STARTED;
 import static de.latlon.xplanbox.validator.storage.StatusType.IMPORT_FAILED;
 import static de.latlon.xplanbox.validator.storage.exception.ErrorType.INTERNAL_ERROR;
@@ -88,8 +89,8 @@ public class PlanImporter {
 
 	private void doImportPlan(ImportRequestedEvent event) throws Exception {
 		validationExecutionStorage.changeStatus(event.getUuid(), StatusType.IMPORT_STARTED);
-		eventSender.sendPublicEvent(new XPlanPublicV1Event(IMPORT_STARTED, event.getUuid(), "import started"),
-				"routing.suffix.for.import-started.to.be.determined");
+		eventSender.sendPublicEvent(new XPlanPublicV1Event(IMPORT_STARTED, event.getUuid()),
+				IMPORT_STARTED.routingKeySuffix());
 		Path tmpPath = Files.createTempFile(event.getUuid(), ".rcv");
 		if (Files.exists(tmpPath))
 			Files.delete(tmpPath);
@@ -119,8 +120,8 @@ public class PlanImporter {
 		}
 		finally {
 			Files.delete(tmpPath);
-			eventSender.sendPublicEvent(new XPlanPublicV1Event(XPlanPublicV1Event.EventType.IMPORT_FINISHED,
-					event.getUuid(), "import finished"), "routing.suffix.for.import-finished.to.be.determined");
+			eventSender.sendPublicEvent(new XPlanPublicV1Event(IMPORT_FINISHED, event.getUuid()),
+					IMPORT_FINISHED.routingKeySuffix());
 		}
 	}
 
diff --git a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/handler/PlanHandler.java b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/handler/PlanHandler.java
index 2f58e2d8d..d98e96136 100644
--- a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/handler/PlanHandler.java
+++ b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/handler/PlanHandler.java
@@ -137,7 +137,7 @@ public class PlanHandler {
 	}
 
 	public List<Bereich> findBereiche(String planId) {
-		LOG.info("Finding Bereiche of plan with dd '{}'", planId);
+		LOG.info("Finding Bereiche of plan with id '{}'", planId);
 		return xPlanDao.retrieveBereicheOfPlanWithId(planId)
 			.stream()
 			.map(bereich -> new Bereich().name(bereich.getName()).nummer(bereich.getNummer()))
@@ -145,7 +145,7 @@ public class PlanHandler {
 	}
 
 	public List<Gemeinde> findGemeinden(String planId) {
-		LOG.info("Finding Bereiche of plan with dd '{}'", planId);
+		LOG.info("Finding Gemeinden of plan with id '{}'", planId);
 		return xPlanDao.retrieveGemeindeOfPlanWithId(planId)
 			.stream()
 			.map(gemeinde -> new Gemeinde().ags(gemeinde.getAgs())
diff --git a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/messagingrabbitmq/Receiver.java b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/messagingrabbitmq/Receiver.java
index 5a739c385..9ca6e7e98 100644
--- a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/messagingrabbitmq/Receiver.java
+++ b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/messagingrabbitmq/Receiver.java
@@ -59,13 +59,13 @@ public class Receiver {
 			planImporter.importPlan(event);
 
 			ImportFinishedEvent finishedEvent = new ImportFinishedEvent(event.getUuid(), IMPORT_SUCCEEDED);
-			eventSender.sendEvent(finishedEvent);
+			eventSender.sendPrivateEvent(finishedEvent);
 		}
 		catch (Exception e) {
 			LOG.error("Failed to process event. Discarding it", e);
 
 			ImportFinishedEvent finishedEvent = new ImportFinishedEvent(event.getUuid(), IMPORT_FAILED);
-			eventSender.sendEvent(finishedEvent);
+			eventSender.sendPrivateEvent(finishedEvent);
 		}
 	}
 
diff --git a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v2/PlanApi2.java b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v2/PlanApi2.java
index 5a6ce31ec..617b1c5e6 100644
--- a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v2/PlanApi2.java
+++ b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v2/PlanApi2.java
@@ -267,7 +267,7 @@ public class PlanApi2 {
 				overwriteByRequest(skipLaufrichtung, validationConfig.isSkipLaufrichtung()), profiles,
 				WITH_SKIP_RASTER_EVALUATION);
 
-		eventSender.sendEvent(new ImportValidationRequestedEvent(uuid, validationSettings, xFilename, internalId,
+		eventSender.sendPrivateEvent(new ImportValidationRequestedEvent(uuid, validationSettings, xFilename, internalId,
 				planStatus, ValidationRequestedEvent.MediaType.JSON, originFile, false));
 
 		URI linkToStatus = createLinkToStatus(uuid);
diff --git a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/executor/PlanImporterTest.java b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/executor/PlanImporterTest.java
index ffcb792fc..a5e184edc 100644
--- a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/executor/PlanImporterTest.java
+++ b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/executor/PlanImporterTest.java
@@ -100,12 +100,12 @@ public class PlanImporterTest {
 
 		verify(validationExecutionStorage).cleanupAfterValidation(uuid);
 
-		XPlanPublicV1Event expectedStartEvent = new XPlanPublicV1Event(IMPORT_STARTED, uuid, "import started");
-		XPlanPublicV1Event expectedFinishedEvent = new XPlanPublicV1Event(IMPORT_FINISHED, uuid, "import finished");
+		XPlanPublicV1Event expectedStartEvent = new XPlanPublicV1Event(IMPORT_STARTED, uuid);
+		XPlanPublicV1Event expectedFinishedEvent = new XPlanPublicV1Event(IMPORT_FINISHED, uuid, true);
 		verify(eventSender, times(2)).sendPublicEvent(publicEventCaptor.capture(), stringCaptor.capture());
 		assertThat(publicEventCaptor.getAllValues()).containsExactly(expectedStartEvent, expectedFinishedEvent);
-		assertThat(stringCaptor.getAllValues()).containsExactly("routing.suffix.for.import-started.to.be.determined",
-				"routing.suffix.for.import-finished.to.be.determined");
+		assertThat(stringCaptor.getAllValues()).containsExactly(IMPORT_STARTED.routingKeySuffix(),
+				IMPORT_FINISHED.routingKeySuffix());
 	}
 
 }
diff --git a/xplan-tests/xplan-tests-integration/src/test/java/de/latlon/xplanbox/tests/TestConfig.java b/xplan-tests/xplan-tests-integration/src/test/java/de/latlon/xplanbox/tests/TestConfig.java
index 28f1f110a..bd3cad8ce 100644
--- a/xplan-tests/xplan-tests-integration/src/test/java/de/latlon/xplanbox/tests/TestConfig.java
+++ b/xplan-tests/xplan-tests-integration/src/test/java/de/latlon/xplanbox/tests/TestConfig.java
@@ -53,7 +53,7 @@ public record TestConfig(String dokumenteApiBaseUrl, String managerApiBaseUrl, S
 		int rabbitPort = Integer.parseInt(getEnv("XPLAN_RABBIT_PORT", "5672"), 10);
 		String rabbitUsername = getEnv("XPLAN_RABBIT_USER", "guest");
 		String rabbitPassword = getEnv("XPLAN_RABBIT_PASSWORD", "guest");
-		String publicTopicName = getEnv("XPLAN_RABBIT_PUBLIC_TOPIC", "xplanbox-public");
+		String publicTopicName = getEnv("XPLAN_RABBIT_PUBLIC_TOPIC", "latlon.public");
 		String publicTopicRoutingPrefix = getEnv("XPLAN_RABBIT_PUBLIC_TOPIC_ROUTING_PREFIX", "");
 
 		RabbitConfig rabbitConfig = new RabbitConfig(rabbitHost, rabbitPort, rabbitUsername, rabbitPassword,
diff --git a/xplan-tests/xplan-tests-integration/src/test/java/de/latlon/xplanbox/tests/rabbit/manager/ManagerPublicEventsIT.java b/xplan-tests/xplan-tests-integration/src/test/java/de/latlon/xplanbox/tests/rabbit/manager/ManagerPublicEventsIT.java
index abf842256..9b404be43 100644
--- a/xplan-tests/xplan-tests-integration/src/test/java/de/latlon/xplanbox/tests/rabbit/manager/ManagerPublicEventsIT.java
+++ b/xplan-tests/xplan-tests-integration/src/test/java/de/latlon/xplanbox/tests/rabbit/manager/ManagerPublicEventsIT.java
@@ -5,14 +5,13 @@ import static org.assertj.core.api.Assertions.assertThat;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable;
-
 import de.latlon.xplanbox.tests.FeignUtils;
 import de.latlon.xplanbox.tests.TestConfig;
 import de.latlon.xplanbox.tests.rabbit.AbstractRabbitITExecution;
 import feign.Feign;
 import feign.jackson.JacksonDecoder;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable;
 
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz</a>
@@ -25,12 +24,12 @@ class ManagerPublicEventsIT extends AbstractRabbitITExecution {
 
 	@Test
 	void importAndVerifyPublicEvents() throws Exception {
-		ManagerApiV2 v2Api = Feign.builder() //
+		ManagerApiV2 v2Api = Feign.builder()
 			.client(FeignUtils.unsecuredClient())
-			// .logger(new Logger.ErrorLogger()) //
-			// .logLevel(Level.FULL) //
-			.encoder(new SimpleBodyFileEncoder()) //
-			.decoder(new JacksonDecoder()) //
+			// .logger(new Logger.ErrorLogger())
+			// .logLevel(Level.FULL)
+			.encoder(new SimpleBodyFileEncoder())
+			.decoder(new JacksonDecoder())
 			.target(ManagerApiV2.class, testConfig.managerApiBaseUrl());
 
 		startRabbitPublicEventsReception(testConfig.rabbitConfig());
@@ -46,34 +45,67 @@ class ManagerPublicEventsIT extends AbstractRabbitITExecution {
 		assertThat(statusResponse.status()).isIn("VALIDATION_REQUESTED", "VALIDATION_FINISHED", "IMPORT_REQUESTED",
 				"IMPORT_FINISHED");
 
-		// awaiting 4 events for this uuid
+		// awaiting 10 events for this uuid
 		ReceivedPublicEvent expectedEventValidationStarted = new ReceivedPublicEvent(
-				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "routing.suffix.for.started.to.be.determined",
+				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "xplanbox.validation",
 				"{\"apiVersion\":\"1.0\",\"eventType\":\"VALIDATION_STARTED\",\"uuid\":\"" + r.uuid()
-						+ "\",\"message\":\"validation started\"}");
+						+ "\",\"valid\":null,\"error\":null}");
+
+		ReceivedPublicEvent expectedEventSynValidationStarted = new ReceivedPublicEvent(
+				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "xplanbox.validation.syntaktisch",
+				"{\"apiVersion\":\"1.0\",\"eventType\":\"SYNTACTIC_VALIDATION_STARTED\",\"uuid\":\"" + r.uuid()
+						+ "\",\"valid\":null,\"error\":null}");
+		ReceivedPublicEvent expectedEventSynValidationFinished = new ReceivedPublicEvent(
+				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "xplanbox.validation.syntaktisch",
+				"{\"apiVersion\":\"1.0\",\"eventType\":\"SYNTACTIC_VALIDATION_FINISHED\",\"uuid\":\"" + r.uuid()
+						+ "\",\"valid\":true,\"error\":null}");
+
+		ReceivedPublicEvent expectedEventGeomValidationStarted = new ReceivedPublicEvent(
+				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "xplanbox.validation.geometrisch",
+				"{\"apiVersion\":\"1.0\",\"eventType\":\"GEOMETRIC_VALIDATION_STARTED\",\"uuid\":\"" + r.uuid()
+						+ "\",\"valid\":null,\"error\":null}");
+		ReceivedPublicEvent expectedEventGeomValidationFinished = new ReceivedPublicEvent(
+				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "xplanbox.validation.geometrisch",
+				"{\"apiVersion\":\"1.0\",\"eventType\":\"GEOMETRIC_VALIDATION_FINISHED\",\"uuid\":\"" + r.uuid()
+						+ "\",\"valid\":true,\"error\":null}");
+
+		ReceivedPublicEvent expectedEventSemValidationStarted = new ReceivedPublicEvent(
+				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "xplanbox.validation.semantisch",
+				"{\"apiVersion\":\"1.0\",\"eventType\":\"SEMANTIC_VALIDATION_STARTED\",\"uuid\":\"" + r.uuid()
+						+ "\",\"valid\":null,\"error\":null}");
+		ReceivedPublicEvent expectedEventSemValidationFinished = new ReceivedPublicEvent(
+				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "xplanbox.validation.semantisch",
+				"{\"apiVersion\":\"1.0\",\"eventType\":\"SEMANTIC_VALIDATION_FINISHED\",\"uuid\":\"" + r.uuid()
+						+ "\",\"valid\":true,\"error\":null}");
+
 		ReceivedPublicEvent expectedEventValidationFinished = new ReceivedPublicEvent(
-				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "routing.suffix.for.finished.to.be.determined",
+				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "xplanbox.validation",
 				"{\"apiVersion\":\"1.0\",\"eventType\":\"VALIDATION_FINISHED\",\"uuid\":\"" + r.uuid()
-						+ "\",\"message\":\"validation finished\"}");
+						+ "\",\"valid\":true,\"error\":null}");
+
 		ReceivedPublicEvent expectedEventImportStarted = new ReceivedPublicEvent(
 				testConfig.rabbitConfig().publicTopicRoutingPrefix()
 						+ "routing.suffix.for.import-started.to.be.determined",
 				"{\"apiVersion\":\"1.0\",\"eventType\":\"IMPORT_STARTED\",\"uuid\":\"" + r.uuid()
-						+ "\",\"message\":\"import started\"}");
+						+ "\",\"valid\":true,\"error\":null}");
+
 		ReceivedPublicEvent expectedEventImportFinished = new ReceivedPublicEvent(
 				testConfig.rabbitConfig().publicTopicRoutingPrefix()
 						+ "routing.suffix.for.import-finished.to.be.determined",
 				"{\"apiVersion\":\"1.0\",\"eventType\":\"IMPORT_FINISHED\",\"uuid\":\"" + r.uuid()
-						+ "\",\"message\":\"import finished\"}");
+						+ "\",\"valid\":true,\"error\":null}");
 
-		waitingIfNeeded(20,
+		waitingIfNeeded(30,
 				() -> assertThat(receivedEventsFor(r.uuid())).containsExactly(expectedEventValidationStarted,
+						expectedEventSynValidationStarted, expectedEventSynValidationFinished,
+						expectedEventGeomValidationStarted, expectedEventGeomValidationFinished,
+						expectedEventSemValidationStarted, expectedEventSemValidationFinished,
 						expectedEventValidationFinished, expectedEventImportStarted, expectedEventImportFinished));
 
 		// verify status
 		statusResponse = v2Api.status(r.uuid());
-		assertThat(statusResponse.status()).isEqualTo("IMPORT_FINISHED"); // now surely
-																			// finished
+		// now surely finished
+		assertThat(statusResponse.status()).isEqualTo("IMPORT_FINISHED");
 	}
 
 }
diff --git a/xplan-tests/xplan-tests-integration/src/test/java/de/latlon/xplanbox/tests/rabbit/validator/ValidationPublicEventsIT.java b/xplan-tests/xplan-tests-integration/src/test/java/de/latlon/xplanbox/tests/rabbit/validator/ValidationPublicEventsIT.java
index 79decc1a0..e9fa44eb0 100644
--- a/xplan-tests/xplan-tests-integration/src/test/java/de/latlon/xplanbox/tests/rabbit/validator/ValidationPublicEventsIT.java
+++ b/xplan-tests/xplan-tests-integration/src/test/java/de/latlon/xplanbox/tests/rabbit/validator/ValidationPublicEventsIT.java
@@ -5,9 +5,6 @@ import static org.assertj.core.api.Assertions.assertThat;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable;
-
 import de.latlon.xplanbox.tests.FeignUtils;
 import de.latlon.xplanbox.tests.TestConfig;
 import de.latlon.xplanbox.tests.rabbit.AbstractRabbitITExecution;
@@ -16,6 +13,8 @@ import de.latlon.xplanbox.tests.validatorapi.ValidatorApi.StatusResponse;
 import de.latlon.xplanbox.tests.validatorapi.ValidatorApi.ValidateResponse;
 import feign.Feign;
 import feign.jackson.JacksonDecoder;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable;
 
 /**
  * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
@@ -24,16 +23,14 @@ import feign.jackson.JacksonDecoder;
 @DisabledIfEnvironmentVariable(named = "SKIP_RABBIT_TESTS", matches = "(1|true)")
 class ValidationPublicEventsIT extends AbstractRabbitITExecution {
 
-	private TestConfig testConfig = TestConfig.getTestConfig();
+	private final TestConfig testConfig = TestConfig.getTestConfig();
 
 	@Test
 	void validateAndVerifyPublicEvents() throws Exception {
-		ValidatorApi validatorApi = Feign.builder() //
+		ValidatorApi validatorApi = Feign.builder()
 			.client(FeignUtils.unsecuredClient())
-			// .logger(new Logger.ErrorLogger()) //
-			// .logLevel(Level.FULL) //
-			.encoder(new SimpleBodyFileEncoder()) //
-			.decoder(new JacksonDecoder()) //
+			.encoder(new SimpleBodyFileEncoder())
+			.decoder(new JacksonDecoder())
 			.target(ValidatorApi.class, testConfig.validatorApiBaseUrl());
 
 		startRabbitPublicEventsReception(testConfig.rabbitConfig());
@@ -46,25 +43,56 @@ class ValidationPublicEventsIT extends AbstractRabbitITExecution {
 
 		// verify status (probably not yet finished but who knows...)
 		StatusResponse statusResponse = validatorApi.v2Status(r.uuid());
-		assertThat(statusResponse.status()).isIn("VALIDATION_REQUESTED", "VALIDATION_FINISHED"); // ....
+		assertThat(statusResponse.status()).isIn("VALIDATION_REQUESTED", "VALIDATION_FINISHED");
 
-		// awaiting 2 events for this uuid
+		// awaiting 8 events for this uuid
 		ReceivedPublicEvent expectedEventValidationStarted = new ReceivedPublicEvent(
-				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "routing.suffix.for.started.to.be.determined",
+				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "xplanbox.validation",
 				"{\"apiVersion\":\"1.0\",\"eventType\":\"VALIDATION_STARTED\",\"uuid\":\"" + r.uuid()
-						+ "\",\"message\":\"validation started\"}");
+						+ "\",\"valid\":null,\"error\":null}");
+
+		ReceivedPublicEvent expectedEventSynValidationStarted = new ReceivedPublicEvent(
+				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "xplanbox.validation.syntaktisch",
+				"{\"apiVersion\":\"1.0\",\"eventType\":\"SYNTACTIC_VALIDATION_STARTED\",\"uuid\":\"" + r.uuid()
+						+ "\",\"valid\":null,\"error\":null}");
+		ReceivedPublicEvent expectedEventSynValidationFinished = new ReceivedPublicEvent(
+				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "xplanbox.validation.syntaktisch",
+				"{\"apiVersion\":\"1.0\",\"eventType\":\"SYNTACTIC_VALIDATION_FINISHED\",\"uuid\":\"" + r.uuid()
+						+ "\",\"valid\":true,\"error\":null}");
+
+		ReceivedPublicEvent expectedEventGeomValidationStarted = new ReceivedPublicEvent(
+				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "xplanbox.validation.geometrisch",
+				"{\"apiVersion\":\"1.0\",\"eventType\":\"GEOMETRIC_VALIDATION_STARTED\",\"uuid\":\"" + r.uuid()
+						+ "\",\"valid\":null,\"error\":null}");
+		ReceivedPublicEvent expectedEventGeomValidationFinished = new ReceivedPublicEvent(
+				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "xplanbox.validation.geometrisch",
+				"{\"apiVersion\":\"1.0\",\"eventType\":\"GEOMETRIC_VALIDATION_FINISHED\",\"uuid\":\"" + r.uuid()
+						+ "\",\"valid\":true,\"error\":null}");
+
+		ReceivedPublicEvent expectedEventSemValidationStarted = new ReceivedPublicEvent(
+				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "xplanbox.validation.semantisch",
+				"{\"apiVersion\":\"1.0\",\"eventType\":\"SEMANTIC_VALIDATION_STARTED\",\"uuid\":\"" + r.uuid()
+						+ "\",\"valid\":null,\"error\":null}");
+		ReceivedPublicEvent expectedEventSemValidationFinished = new ReceivedPublicEvent(
+				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "xplanbox.validation.semantisch",
+				"{\"apiVersion\":\"1.0\",\"eventType\":\"SEMANTIC_VALIDATION_FINISHED\",\"uuid\":\"" + r.uuid()
+						+ "\",\"valid\":true,\"error\":null}");
+
 		ReceivedPublicEvent expectedEventValidationFinished = new ReceivedPublicEvent(
-				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "routing.suffix.for.finished.to.be.determined",
+				testConfig.rabbitConfig().publicTopicRoutingPrefix() + "xplanbox.validation",
 				"{\"apiVersion\":\"1.0\",\"eventType\":\"VALIDATION_FINISHED\",\"uuid\":\"" + r.uuid()
-						+ "\",\"message\":\"validation finished\"}");
-		waitingIfNeeded(10, () -> assertThat(receivedEventsFor(r.uuid()))
-			.containsExactly(expectedEventValidationStarted, expectedEventValidationFinished));
+						+ "\",\"valid\":true,\"error\":null}");
+		waitingIfNeeded(20,
+				() -> assertThat(receivedEventsFor(r.uuid())).containsExactly(expectedEventValidationStarted,
+						expectedEventSynValidationStarted, expectedEventSynValidationFinished,
+						expectedEventGeomValidationStarted, expectedEventGeomValidationFinished,
+						expectedEventSemValidationStarted, expectedEventSemValidationFinished,
+						expectedEventValidationFinished));
 
 		// verify status
 		statusResponse = validatorApi.v2Status(r.uuid());
-		assertThat(statusResponse.status()).isEqualTo("VALIDATION_FINISHED"); // now
-																				// surely
-																				// finished
+		// now surely finished
+		assertThat(statusResponse.status()).isEqualTo("VALIDATION_FINISHED");
 	}
 
 }
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/ValidateApi2.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/ValidateApi2.java
index 83961d901..98079b05e 100644
--- a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/ValidateApi2.java
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/ValidateApi2.java
@@ -179,7 +179,7 @@ public class ValidateApi2 {
 				skipFlaechenschluss, skipGeltungsbereich, skipLaufrichtung, profiles,
 				validatorApiConfiguration.isSkipRasterEvaluation());
 
-		validationRequestNotifier.sendEvent(new ValidationRequestedEvent(uuid, settings, xFilename,
+		validationRequestNotifier.sendPrivateEvent(new ValidationRequestedEvent(uuid, settings, xFilename,
 				ValidationRequestedEvent.MediaType.JSON, originFile));
 
 		URI linkToStatus = createLinkToStatus(uuid);
diff --git a/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/PlanValidator.java b/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/PlanValidator.java
index d0f0e8b32..d6a735d79 100644
--- a/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/PlanValidator.java
+++ b/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/PlanValidator.java
@@ -1,5 +1,7 @@
 package de.latlon.xplanbox.validator.executor;
 
+import static de.latlon.core.validator.events.v1.XPlanPublicV1Event.EventType.VALIDATION_FINISHED;
+import static de.latlon.core.validator.events.v1.XPlanPublicV1Event.EventType.VALIDATION_STARTED;
 import static de.latlon.xplan.validator.report.geojson.GeoJsonBuilder.createGeoJsonFailures;
 import static de.latlon.xplanbox.validator.storage.StatusType.VALIDATION_FAILED;
 import static de.latlon.xplanbox.validator.storage.exception.ErrorType.INTERNAL_ERROR;
@@ -17,7 +19,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import de.latlon.core.validator.events.EventSender;
 import de.latlon.core.validator.events.ValidationRequestedEvent;
 import de.latlon.core.validator.events.v1.XPlanPublicV1Event;
-import de.latlon.core.validator.events.v1.XPlanPublicV1Event.EventType;
 import de.latlon.xplan.commons.archive.XPlanArchive;
 import de.latlon.xplan.validator.ValidatorException;
 import de.latlon.xplan.validator.report.ReportGenerationException;
@@ -25,9 +26,9 @@ import de.latlon.xplan.validator.report.ValidatorReport;
 import de.latlon.xplan.validator.report.geojson.model.FeatureCollection;
 import de.latlon.xplanbox.api.commons.ObjectMapperContextResolver;
 import de.latlon.xplanbox.api.commons.ValidationReportBuilder;
+import de.latlon.xplanbox.api.commons.exception.InvalidXPlanGmlOrArchive;
 import de.latlon.xplanbox.api.commons.exception.XPlanApiException;
 import de.latlon.xplanbox.api.commons.v2.model.ValidationReport;
-import de.latlon.xplanbox.core.raster.evaluation.XPlanRasterEvaluator;
 import de.latlon.xplanbox.validator.executor.handler.ValidationHandler;
 import de.latlon.xplanbox.validator.storage.StatusType;
 import de.latlon.xplanbox.validator.storage.StoredValidationReport;
@@ -52,13 +53,10 @@ public class PlanValidator {
 
 	private final EventSender eventSender;
 
-	private XPlanRasterEvaluator xPlanRasterEvaluator;
-
 	public PlanValidator(ValidationExecutionStorage validationExecutionStorage, ValidationHandler validationHandler,
-			XPlanRasterEvaluator xPlanRasterEvaluator, EventSender eventSender) {
+			EventSender eventSender) {
 		this.validationExecutionStorage = validationExecutionStorage;
 		this.validationHandler = validationHandler;
-		this.xPlanRasterEvaluator = xPlanRasterEvaluator;
 		this.eventSender = eventSender;
 	}
 
@@ -72,49 +70,25 @@ public class PlanValidator {
 
 	private ValidationReport validate(ValidationRequestedEvent event, boolean cleanUp) throws Exception {
 		validationExecutionStorage.changeStatus(event.getUuid(), StatusType.VALIDATION_STARTED);
-		eventSender.sendPublicEvent(
-				new XPlanPublicV1Event(EventType.VALIDATION_STARTED, event.getUuid(), "validation started"),
-				"routing.suffix.for.started.to.be.determined");
-
-		try {
-			return doValidate(event, cleanUp);
-		}
-		finally {
-			eventSender.sendPublicEvent(
-					new XPlanPublicV1Event(EventType.VALIDATION_FINISHED, event.getUuid(), "validation finished"),
-					"routing.suffix.for.finished.to.be.determined");
-		}
+		eventSender.sendPublicEvent(new XPlanPublicV1Event(VALIDATION_STARTED, event.getUuid()),
+				VALIDATION_STARTED.routingKeySuffix());
+		return doValidate(event, cleanUp);
 	}
 
 	private ValidationReport doValidate(ValidationRequestedEvent event, boolean cleanUp) throws Exception {
 		Map<ReportType, Path> reports = new HashMap<>();
+		Path tmpPath = null;
 		try {
-			Path tmpPath = Files.createTempFile(event.getUuid(), ".rcv");
-			if (Files.exists(tmpPath))
-				Files.delete(tmpPath);
+			tmpPath = createTmpPath(event);
 			validationExecutionStorage.writePlanToValidate(event.getUuid(), tmpPath);
 
-			final XPlanArchive archive;
-			if (event.getOriginFile() == ValidationRequestedEvent.OriginFile.GML) {
-				archive = validationHandler.createArchiveFromGml(tmpPath.toFile(),
-						event.getSettings().getValidationName());
-			}
-			else {
-				archive = validationHandler.createArchiveFromZip(tmpPath.toFile(),
-						event.getSettings().getValidationName());
-			}
+			XPlanArchive archive = readAsArchive(event, tmpPath);
 
 			LOG.info("Validating {}", tmpPath);
-			ValidatorReport validatorReport = validationHandler.validate(archive, event.getxFileName(),
+			ValidatorReport validatorReport = validationHandler.validate(event.getUuid(), archive, event.getxFileName(),
 					event.getSettings());
-			// TODO: delete tmpPath
 
-			ValidationReport validationReport = createValidationReport(event, archive, validatorReport);
-
-			reports.put(ReportType.JSON, createJsonReportFile(validationReport));
-			reports.put(ReportType.GEOJSON, createGeoJsonReportFile(validatorReport));
-			reports.put(ReportType.PDF, createPdfReportFile(validatorReport));
-			reports.put(ReportType.ZIP, createZipReportFile(validatorReport));
+			ValidationReport validationReport = createAndAddReports(event, archive, validatorReport, reports);
 
 			StoredValidationReport storedValidationReport = validationExecutionStorage
 				.saveValidationResult(event.getUuid(), reports);
@@ -123,6 +97,9 @@ public class PlanValidator {
 					storedValidationReport);
 			if (cleanUp && validatorReport.isValid())
 				validationExecutionStorage.cleanupAfterValidation(event.getUuid());
+			eventSender.sendPublicEvent(
+					new XPlanPublicV1Event(VALIDATION_FINISHED, event.getUuid(), validatorReport.isValid()),
+					VALIDATION_FINISHED.routingKeySuffix());
 			return validationReport;
 		}
 		catch (XPlanApiException e) {
@@ -146,7 +123,39 @@ public class PlanValidator {
 			for (Path path : reports.values()) {
 				Files.deleteIfExists(path);
 			}
+			if (tmpPath != null)
+				Files.deleteIfExists(tmpPath);
+		}
+	}
+
+	private ValidationReport createAndAddReports(ValidationRequestedEvent event, XPlanArchive archive,
+			ValidatorReport validatorReport, Map<ReportType, Path> reports)
+			throws IOException, ReportGenerationException {
+		ValidationReport validationReport = createValidationReport(event, archive, validatorReport);
+
+		reports.put(ReportType.JSON, createJsonReportFile(validationReport));
+		reports.put(ReportType.GEOJSON, createGeoJsonReportFile(validatorReport));
+		reports.put(ReportType.PDF, createPdfReportFile(validatorReport));
+		reports.put(ReportType.ZIP, createZipReportFile(validatorReport));
+		return validationReport;
+	}
+
+	private static Path createTmpPath(ValidationRequestedEvent event) throws IOException {
+		Path tmpPath = Files.createTempFile(event.getUuid(), ".rcv");
+		if (Files.exists(tmpPath))
+			Files.delete(tmpPath);
+		return tmpPath;
+	}
+
+	private XPlanArchive readAsArchive(ValidationRequestedEvent event, Path tmpPath) throws InvalidXPlanGmlOrArchive {
+		final XPlanArchive archive;
+		if (event.getOriginFile() == ValidationRequestedEvent.OriginFile.GML) {
+			archive = validationHandler.createArchiveFromGml(tmpPath.toFile(), event.getSettings().getValidationName());
+		}
+		else {
+			archive = validationHandler.createArchiveFromZip(tmpPath.toFile(), event.getSettings().getValidationName());
 		}
+		return archive;
 	}
 
 	private ValidationReport createValidationReport(ValidationRequestedEvent event, final XPlanArchive archive,
diff --git a/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/config/ApplicationContext.java b/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/config/ApplicationContext.java
index 334d07873..01416b14c 100644
--- a/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/config/ApplicationContext.java
+++ b/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/config/ApplicationContext.java
@@ -37,6 +37,7 @@ import de.latlon.xplan.validator.configuration.ValidatorConfiguration;
 import de.latlon.xplan.validator.configuration.ValidatorConfigurationParser;
 import de.latlon.xplan.validator.geometric.GeometricValidator;
 import de.latlon.xplan.validator.geometric.GeometricValidatorImpl;
+import de.latlon.xplan.validator.listener.ValidationProcessListener;
 import de.latlon.xplan.validator.planinfo.PlanInfoParser;
 import de.latlon.xplan.validator.report.ReportArchiveGenerator;
 import de.latlon.xplan.validator.report.ReportWriter;
@@ -130,9 +131,11 @@ public class ApplicationContext {
 	@Bean
 	public XPlanValidator xplanValidator(GeometricValidator geometricValidator, SyntacticValidator syntacticValidator,
 			SemanticValidator semanticValidator, SemanticProfiles semanticProfiles,
-			ReportArchiveGenerator reportArchiveGenerator, PlanInfoParser planInfoParser) {
+			ReportArchiveGenerator reportArchiveGenerator, PlanInfoParser planInfoParser,
+			ValidationProcessListener validationProcessListener) {
 		return new XPlanValidator(geometricValidator, syntacticValidator, semanticValidator,
-				semanticProfiles.getProfileValidators(), reportArchiveGenerator, planInfoParser);
+				semanticProfiles.getProfileValidators(), reportArchiveGenerator, planInfoParser,
+				validationProcessListener);
 	}
 
 	@Bean
diff --git a/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/handler/ValidationHandler.java b/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/handler/ValidationHandler.java
index 50f6df0ef..daee7d6e6 100644
--- a/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/handler/ValidationHandler.java
+++ b/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/handler/ValidationHandler.java
@@ -8,12 +8,12 @@
  * it under the terms of the GNU Affero General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  * #L%
@@ -83,10 +83,10 @@ public class ValidationHandler {
 
 	private XPlanArchiveCreator archiveCreator = new XPlanArchiveCreator();
 
-	public ValidatorReport validate(XPlanArchive archive, String xFileName, ValidationSettings validationSettings)
-			throws ValidatorException {
+	public ValidatorReport validate(String uuid, XPlanArchive archive, String xFileName,
+			ValidationSettings validationSettings) throws ValidatorException {
 		LOG.debug("Validate plan with validationName {}", validationSettings.getValidationName());
-		return xPlanValidator.validateNotWriteReport(validationSettings, archive, xFileName);
+		return xPlanValidator.validateNotWriteReport(uuid, validationSettings, archive, xFileName);
 	}
 
 	public Path zipReports(ValidatorReport validatorReport) throws IOException {
diff --git a/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/listener/EventValidationProcessListener.java b/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/listener/EventValidationProcessListener.java
new file mode 100644
index 000000000..17f583e96
--- /dev/null
+++ b/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/listener/EventValidationProcessListener.java
@@ -0,0 +1,82 @@
+package de.latlon.xplanbox.validator.executor.listener;
+
+import static de.latlon.core.validator.events.v1.XPlanPublicV1Event.EventType.GEOMETRIC_VALIDATION_FINISHED;
+import static de.latlon.core.validator.events.v1.XPlanPublicV1Event.EventType.GEOMETRIC_VALIDATION_STARTED;
+import static de.latlon.core.validator.events.v1.XPlanPublicV1Event.EventType.PROFILE_VALIDATION_FINISHED;
+import static de.latlon.core.validator.events.v1.XPlanPublicV1Event.EventType.PROFILE_VALIDATION_STARTED;
+import static de.latlon.core.validator.events.v1.XPlanPublicV1Event.EventType.SEMANTIC_VALIDATION_FINISHED;
+import static de.latlon.core.validator.events.v1.XPlanPublicV1Event.EventType.SEMANTIC_VALIDATION_STARTED;
+import static de.latlon.core.validator.events.v1.XPlanPublicV1Event.EventType.SYNTACTIC_VALIDATION_FINISHED;
+import static de.latlon.core.validator.events.v1.XPlanPublicV1Event.EventType.SYNTACTIC_VALIDATION_STARTED;
+import static de.latlon.core.validator.events.v1.XPlanPublicV1Event.EventType.VALIDATION_FAILED;
+import static de.latlon.core.validator.events.v1.XPlanPublicV1Event.EventType.VALIDATION_STARTED;
+
+import de.latlon.core.validator.events.EventSender;
+import de.latlon.core.validator.events.v1.XPlanPublicV1Event;
+import de.latlon.xplan.validator.listener.ValidationProcessListener;
+import de.latlon.xplan.validator.web.shared.ValidationType;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ */
+@Component
+public class EventValidationProcessListener implements ValidationProcessListener {
+
+	@Autowired
+	private EventSender eventSender;
+
+	@Override
+	public void validationStarted(String uuid) {
+		// handled in PlanValidator.validate
+	}
+
+	@Override
+	public void validationPartStarted(String uuid, ValidationType validationType) {
+		XPlanPublicV1Event.EventType eventType = SYNTACTIC_VALIDATION_STARTED;
+		switch (validationType) {
+			case GEOMETRIC -> eventType = GEOMETRIC_VALIDATION_STARTED;
+			case SEMANTIC -> eventType = SEMANTIC_VALIDATION_STARTED;
+		}
+		XPlanPublicV1Event event = new XPlanPublicV1Event(eventType, uuid);
+		eventSender.sendPublicEvent(event, eventType.routingKeySuffix());
+	}
+
+	@Override
+	public void validationPartFinished(String uuid, ValidationType validationType, Boolean isValid) {
+		XPlanPublicV1Event.EventType eventType = SYNTACTIC_VALIDATION_FINISHED;
+		switch (validationType) {
+			case GEOMETRIC -> eventType = GEOMETRIC_VALIDATION_FINISHED;
+			case SEMANTIC -> eventType = SEMANTIC_VALIDATION_FINISHED;
+		}
+		XPlanPublicV1Event event = new XPlanPublicV1Event(eventType, uuid, isValid);
+		eventSender.sendPublicEvent(event, eventType.routingKeySuffix());
+	}
+
+	@Override
+	public void validationProfileStarted(String uuid, String profileId) {
+		XPlanPublicV1Event event = new XPlanPublicV1Event(PROFILE_VALIDATION_STARTED, uuid);
+		eventSender.sendPublicEvent(event, PROFILE_VALIDATION_STARTED.routingKeySuffix() + profileId);
+
+	}
+
+	@Override
+	public void validationProfileFinished(String uuid, String profileId, Boolean isValid) {
+		XPlanPublicV1Event event = new XPlanPublicV1Event(PROFILE_VALIDATION_FINISHED, uuid, isValid);
+		eventSender.sendPublicEvent(event, PROFILE_VALIDATION_FINISHED.routingKeySuffix() + profileId);
+	}
+
+	@Override
+	public void validationFinished(String uuid, Boolean isValid) {
+		// handled in PlanValidator.validate
+	}
+
+	@Override
+	public void validationFailed(String uuid, String error) {
+		XPlanPublicV1Event event = new XPlanPublicV1Event(VALIDATION_FAILED, uuid, error);
+		eventSender.sendPublicEvent(event, VALIDATION_STARTED.routingKeySuffix());
+
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/messagingrabbitmq/Receiver.java b/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/messagingrabbitmq/Receiver.java
index 47e24f008..d5d14aa13 100644
--- a/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/messagingrabbitmq/Receiver.java
+++ b/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/messagingrabbitmq/Receiver.java
@@ -79,13 +79,13 @@ public class Receiver {
 			validator.validateAndCleanUp(event);
 
 			ValidationFinishedEvent finishedEvent = new ValidationFinishedEvent(event.getUuid(), SUCCEEDED);
-			eventSender.sendEvent(finishedEvent);
+			eventSender.sendPrivateEvent(finishedEvent);
 		}
 		catch (Exception e) {
 			LOG.error("Failed to process event. Discarding it", e);
 
 			ValidationFinishedEvent finishedEvent = new ValidationFinishedEvent(event.getUuid(), FAILED);
-			eventSender.sendEvent(finishedEvent);
+			eventSender.sendPrivateEvent(finishedEvent);
 		}
 	}
 
@@ -94,20 +94,20 @@ public class Receiver {
 			ValidationReport validationReport = validator.validate(event);
 
 			ValidationFinishedEvent finishedEvent = new ValidationFinishedEvent(event.getUuid(), SUCCEEDED);
-			eventSender.sendEvent(finishedEvent);
+			eventSender.sendPrivateEvent(finishedEvent);
 			ImportRequestedEvent importRequestedEvent = new ImportRequestedEvent(event.getUuid(),
 					event.getSettings().getValidationName(), event.getInternalId(), event.getPlanStatus(),
 					event.getOriginFile(), ValidationReportUtils.isValid(validationReport) ? VALID : INVALID,
 					rasterEvaluationStatus(validationReport), event.isSupportsGetPlanByIdAsZip());
-			eventSender.sendEvent(importRequestedEvent);
+			eventSender.sendPrivateEvent(importRequestedEvent);
 		}
 		catch (Exception e) {
 			LOG.error("Failed to process event. Discarding it", e);
 
 			ValidationFinishedEvent finishedEvent = new ValidationFinishedEvent(event.getUuid(), FAILED);
-			eventSender.sendEvent(finishedEvent);
+			eventSender.sendPrivateEvent(finishedEvent);
 			ImportFinishedEvent finishedImportEvent = new ImportFinishedEvent(event.getUuid(), VALIDATION_FAILED);
-			eventSender.sendEvent(finishedImportEvent);
+			eventSender.sendPrivateEvent(finishedImportEvent);
 		}
 	}
 
diff --git a/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/PlanValidatorTest.java b/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/PlanValidatorTest.java
index 02fbac962..e9a1cb301 100644
--- a/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/PlanValidatorTest.java
+++ b/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/PlanValidatorTest.java
@@ -29,6 +29,7 @@ import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyList;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import java.nio.charset.StandardCharsets;
@@ -58,7 +59,6 @@ import org.json.JSONObject;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
-import org.mockito.Mockito;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.context.TestConfiguration;
@@ -143,14 +143,28 @@ class PlanValidatorTest {
 
 		verifyExpectedReport(uuid, ReportType.JSON, "report1.expected.json");
 
-		XPlanPublicV1Event expectedStartEvent = new XPlanPublicV1Event(EventType.VALIDATION_STARTED, uuid,
-				"validation started");
-		XPlanPublicV1Event expectedFinishedEvent = new XPlanPublicV1Event(EventType.VALIDATION_FINISHED, uuid,
-				"validation finished");
-		Mockito.verify(eventSender, times(2)).sendPublicEvent(publicEventCaptor.capture(), stringCaptor.capture());
-		assertThat(publicEventCaptor.getAllValues()).containsExactly(expectedStartEvent, expectedFinishedEvent);
-		assertThat(stringCaptor.getAllValues()).containsExactly("routing.suffix.for.started.to.be.determined",
-				"routing.suffix.for.finished.to.be.determined");
+		XPlanPublicV1Event expectedStartEvent = new XPlanPublicV1Event(EventType.VALIDATION_STARTED, uuid);
+		XPlanPublicV1Event expectedSynStartedEvent = new XPlanPublicV1Event(EventType.SYNTACTIC_VALIDATION_STARTED,
+				uuid);
+		XPlanPublicV1Event expectedSynFinishedEvent = new XPlanPublicV1Event(EventType.SYNTACTIC_VALIDATION_FINISHED,
+				uuid, true);
+		XPlanPublicV1Event expectedSemStartedEvent = new XPlanPublicV1Event(EventType.SEMANTIC_VALIDATION_STARTED,
+				uuid);
+		XPlanPublicV1Event expectedSemFinishedEvent = new XPlanPublicV1Event(EventType.SEMANTIC_VALIDATION_FINISHED,
+				uuid, true);
+		XPlanPublicV1Event expectedGeomStartedEvent = new XPlanPublicV1Event(EventType.GEOMETRIC_VALIDATION_STARTED,
+				uuid);
+		XPlanPublicV1Event expectedGeomFinishedEvent = new XPlanPublicV1Event(EventType.GEOMETRIC_VALIDATION_FINISHED,
+				uuid, false);
+		XPlanPublicV1Event expectedFinishedEvent = new XPlanPublicV1Event(EventType.VALIDATION_FINISHED, uuid, false);
+		verify(eventSender, times(8)).sendPublicEvent(publicEventCaptor.capture(), stringCaptor.capture());
+
+		assertThat(publicEventCaptor.getAllValues()).containsExactly(expectedStartEvent, expectedSynStartedEvent,
+				expectedSynFinishedEvent, expectedGeomStartedEvent, expectedGeomFinishedEvent, expectedSemStartedEvent,
+				expectedSemFinishedEvent, expectedFinishedEvent);
+		assertThat(stringCaptor.getAllValues()).containsExactly("validation", "validation.syntaktisch",
+				"validation.syntaktisch", "validation.geometrisch", "validation.geometrisch", "validation.semantisch",
+				"validation.semantisch", "validation");
 	}
 
 	@Test
diff --git a/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/handler/ValidationHandlerTest.java b/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/handler/ValidationHandlerTest.java
index 2c930dd98..cb96eaff9 100644
--- a/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/handler/ValidationHandlerTest.java
+++ b/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/handler/ValidationHandlerTest.java
@@ -111,7 +111,7 @@ public class ValidationHandlerTest {
 		final ValidationSettings settings = Mockito.mock(ValidationSettings.class);
 
 		XPlanArchive archive = validationHandler.createArchiveFromZip(file, "bplan_valid_41");
-		ValidatorReport report = validationHandler.validate(archive, "bplan_valid_41", settings);
+		ValidatorReport report = validationHandler.validate("uuid", archive, "bplan_valid_41", settings);
 		assertTrue(report.isValid());
 		assertTrue(report.getPlanInfoReport().getPlanInfos().values().stream().findFirst().get().isValid());
 	}
-- 
GitLab