diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 6e31291a09c355fc54bf3d3a30d81ee1baff481a..5a1242cbba8832fed358a79f8a804e29c16e00a6 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -72,13 +72,14 @@ maven-build:
 maven-prepare-docker-contexts-apis-and-inspire-plu:
   extends: .maven-prepare-docker-contexts
   variables:
-    mvnProjects: ':xplan-validator-api,:xplan-manager-api,:xplan-dokumente-api,:xplan-webservices-inspireplu'
+    mvnProjects: ':xplan-validator-api,:xplan-manager-api,:xplan-dokumente-api,:xplan-webservices-inspireplu,:xplan-gateway'
   artifacts:
     paths: # 2024.02.02: ~387M
     - './xplan-validator/xplan-validator-api/target/docker/**/tmp/docker-build.tar.gz'
     - './xplan-manager/xplan-manager-api/target/docker/**/tmp/docker-build.tar.gz'
     - './xplan-dokumente/xplan-dokumente-api/target/docker/**/tmp/docker-build.tar.gz'
     - './xplan-webservices/xplan-webservices-inspireplu/target/docker/**/docker-build.tar.gz'
+    - './xplan-gateway/target/docker/**/docker-build.tar.gz'
 
 maven-prepare-docker-contexts-cli:
   extends: .maven-prepare-docker-contexts
diff --git a/gitlab/all-kaniko-builds.gitlab-ci.yml b/gitlab/all-kaniko-builds.gitlab-ci.yml
index d387063e9be8cd80602f56090f97fc635678163e..34217f2c81a2e7e76b697ad7f4df045242e13fa5 100644
--- a/gitlab/all-kaniko-builds.gitlab-ci.yml
+++ b/gitlab/all-kaniko-builds.gitlab-ci.yml
@@ -91,6 +91,15 @@ kaniko:xplan-dokumente-api:
     - maven-prepare-docker-contexts-apis-and-inspire-plu
     - kaniko:xplan-docker-tomcat
 
+kaniko:xplan-gateway:
+  extends: .kaniko:build
+  variables:
+    dockerImageName: xplan-gateway
+    tarGzFile: xplan-gateway/target/docker/xplanbox/xplan-gateway/tmp/docker-build.tar.gz
+  needs:
+    - maven-prepare-docker-contexts-apis-and-inspire-plu
+    - kaniko:xplan-docker-tomcat
+
 kaniko:xplan-inspireplu:
   extends: .kaniko:build
   variables:
diff --git a/pom.xml b/pom.xml
index ed1f0615b5660001b24b02ff6d4eb97f76206acc..c3482b7399789bf5ba1b534d7e8c38203d689e86 100644
--- a/pom.xml
+++ b/pom.xml
@@ -65,6 +65,7 @@
     <module>xplan-database</module>
     <module>xplan-documentation</module>
     <module>xplan-dokumente</module>
+    <module>xplan-gateway</module>
     <module>xplan-manager</module>
     <module>xplan-tests</module>
     <module>xplan-validator</module>
@@ -450,7 +451,7 @@
       <plugin>
         <groupId>io.spring.javaformat</groupId>
         <artifactId>spring-javaformat-maven-plugin</artifactId>
-        <version>0.0.42</version>
+        <version>0.0.43</version>
         <executions>
           <execution>
             <phase>validate</phase>
diff --git a/xplan-cli/src/main/java/de/latlon/xplanbox/cli/manage/config/ManageContext.java b/xplan-cli/src/main/java/de/latlon/xplanbox/cli/manage/config/ManageContext.java
index 4ac957898b67cabd90da703e5f06a266fb4a55da..fa9358cd306f9827315c7955e55884ecdff87bab 100644
--- a/xplan-cli/src/main/java/de/latlon/xplanbox/cli/manage/config/ManageContext.java
+++ b/xplan-cli/src/main/java/de/latlon/xplanbox/cli/manage/config/ManageContext.java
@@ -103,6 +103,7 @@ import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 import org.springframework.context.annotation.Lazy;
+import org.springframework.context.annotation.PropertySource;
 import org.springframework.core.io.ResourceLoader;
 
 /**
@@ -114,6 +115,7 @@ import org.springframework.core.io.ResourceLoader;
 @Configuration
 @Import({ JpaContext.class, AmazonS3RasterStorageContext.class, AmazonS3DocumentStorageContext.class,
 		RasterEvaluationContext.class })
+@PropertySource("classpath:/application.properties")
 public class ManageContext {
 
 	private static final Logger LOG = LoggerFactory.getLogger(ManageContext.class);
diff --git a/xplan-cli/src/main/resources/application.properties b/xplan-cli/src/main/resources/application.properties
index 1450f3433519009588f356f54affa5a83ad9f938..919508fb2532afd86de1a483ba7b930aa691236b 100644
--- a/xplan-cli/src/main/resources/application.properties
+++ b/xplan-cli/src/main/resources/application.properties
@@ -18,5 +18,11 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 # #L%
 ###
-spring.main.allow-bean-definition-overriding=true
 spring.batch.job.enabled=false
+
+xplanbox.s3.accessKeyId=${XPLAN_S3_ACCESS_KEY}
+xplanbox.s3.endpoint.url=${XPLAN_S3_ENDPOINT}
+xplanbox.s3.region=${XPLAN_S3_REGION}
+xplanbox.s3.secretKey=${XPLAN_S3_SECRET_ACCESS_KEY}
+
+xplanbox.services.crs=${XPLAN_SERVICES_DEFAULT_CRS:EPSG:25832}
\ No newline at end of file
diff --git a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/ValidationReportBuilder.java b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/ValidationReportBuilder.java
index 0d802fccdf979fb03b172cc05362182c63ebff67..80143679e936130d28814a76037dce74c4cce42d 100644
--- a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/ValidationReportBuilder.java
+++ b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/ValidationReportBuilder.java
@@ -34,7 +34,6 @@ import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
-import de.latlon.xplan.manager.web.shared.RasterEvaluationResult;
 import de.latlon.xplan.validator.geometric.report.GeometricValidatorResult;
 import de.latlon.xplan.validator.i18n.ValidationMessages;
 import de.latlon.xplan.validator.report.ValidatorReport;
@@ -44,6 +43,7 @@ import de.latlon.xplanbox.api.commons.v1.model.DocumentSummary;
 import de.latlon.xplanbox.api.commons.v1.model.ExternalReferenceResult;
 import de.latlon.xplanbox.api.commons.v1.model.ExternalReferenceStatusEnum;
 import de.latlon.xplanbox.api.commons.v1.model.PlanInfoBbox;
+import de.latlon.xplanbox.api.commons.v1.model.RasterEvaluationResult;
 import de.latlon.xplanbox.api.commons.v1.model.RulesMetadata;
 import de.latlon.xplanbox.api.commons.v1.model.SemanticInvalidRuleResult;
 import de.latlon.xplanbox.api.commons.v1.model.ValidationReport;
@@ -90,6 +90,7 @@ public class ValidationReportBuilder {
 	public ValidationReport build() {
 		ValidationReport validationReport = new ValidationReport();
 		if (validatorReport != null) {
+			List<ExternalReferenceResult> externalReferencesResult = externalReferencesResult();
 			validationReport.date(validatorReport.getDate())
 				.name(validatorReport.getValidationName())
 				.documentSummary(buildDocumentSummary())
@@ -99,7 +100,8 @@ public class ValidationReportBuilder {
 				.bbox(asBBox(validatorReport.getBBoxIn4326()))
 				.filename(filename)
 				.externalReferences(externalReferences())
-				.externalReferencesResult(externalReferencesResult())
+				.externalReferencesResult(externalReferencesResult)
+				.rasterEvaluationResults(rasterEvaluationResults(externalReferencesResult))
 				.wmsUrl(wmsUrl)
 				.rulesMetadata(rulesMetadata())
 				.validationResult(createValidationResult());
@@ -110,7 +112,9 @@ public class ValidationReportBuilder {
 	public de.latlon.xplanbox.api.commons.v2.model.ValidationReport buildV2() {
 		de.latlon.xplanbox.api.commons.v2.model.ValidationReport validationReport = new de.latlon.xplanbox.api.commons.v2.model.ValidationReport();
 		if (validatorReport != null) {
-			LocalDateTime date = validatorReport.getDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+			LocalDateTime date = validatorReport.getDate() != null
+					? validatorReport.getDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime() : null;
+			List<ExternalReferenceResult> externalReferencesResult = externalReferencesResult();
 			validationReport.date(date)
 				.name(validatorReport.getValidationName())
 				.documentSummary(buildDocumentSummary())
@@ -119,7 +123,8 @@ public class ValidationReportBuilder {
 				.status(status())
 				.bbox(asBBox(validatorReport.getBBoxIn4326()))
 				.filename(filename)
-				.externalReferencesResult(externalReferencesResult())
+				.externalReferencesResult(externalReferencesResult)
+				.rasterEvaluationResults(rasterEvaluationResults(externalReferencesResult))
 				.wmsUrl(wmsUrl)
 				.rulesMetadata(rulesMetadata())
 				.validationResult(createValidationResultV2());
@@ -149,6 +154,7 @@ public class ValidationReportBuilder {
 					.map(ExternalReferenceResult::getName)
 					.toList())
 				.externalReferencesResult(validationReportV2.getExternalReferencesResult())
+				.rasterEvaluationResults((validationReportV2.getRasterEvaluationResults()))
 				.wmsUrl(validationReportV2.getWmsUrl())
 				.rulesMetadata(validationReportV2.getRulesMetadata())
 				.validationResult(convertToV1(validationResult));
@@ -225,26 +231,35 @@ public class ValidationReportBuilder {
 				externalReferenceAndStatus.add(new ExternalReferenceResult().name(name)
 					.status(ExternalReferenceStatusEnum.fromExternalReferenceStatus(status)));
 			});
-			List<RasterEvaluationResult> rasterEvaluationResults = validatorReport.getRasterEvaluationResults();
-			rasterEvaluationResults.forEach(rasterEvaluationResult -> {
-				Optional<ExternalReferenceResult> matchingExternalReference = externalReferenceAndStatus.stream()
-					.filter(externalReferenceResult -> externalReferenceResult.getName()
-						.equals(rasterEvaluationResult.getRasterName()))
-					.findFirst();
-				if (matchingExternalReference.isPresent() && rasterEvaluationResult.isRasterFileAvailable()) {
-					CrsStatusEnum crsStatus = CrsStatusEnum.fromResult(rasterEvaluationResult.isConfiguredCrs(),
-							rasterEvaluationResult.isCrsSet());
-					ImageFormatStatusEnum imageFormatStatus = ImageFormatStatusEnum
-						.fromResult(rasterEvaluationResult.isSupportedImageFormat());
-					matchingExternalReference.get().crsStatus(crsStatus).imageFormatStatus(imageFormatStatus);
-				}
-			});
 			return externalReferenceAndStatus;
 		}
 		return null;
 
 	}
 
+	private List<RasterEvaluationResult> rasterEvaluationResults(
+			List<ExternalReferenceResult> externalReferenceAndStatus) {
+		List<RasterEvaluationResult> rasterEvaluationResults = new ArrayList<>();
+		validatorReport.getRasterEvaluationResults().forEach(rasterEvaluationResult -> {
+			Optional<ExternalReferenceResult> matchingExternalReference = externalReferenceAndStatus.stream()
+				.filter(externalReferenceResult -> externalReferenceResult.getName()
+					.equals(rasterEvaluationResult.getRasterName()))
+				.findFirst();
+			if (matchingExternalReference.isPresent() && rasterEvaluationResult.isRasterFileAvailable()) {
+				CrsStatusEnum crsStatus = CrsStatusEnum.fromResult(rasterEvaluationResult.isConfiguredCrs(),
+						rasterEvaluationResult.isCrsSet());
+				ImageFormatStatusEnum imageFormatStatus = ImageFormatStatusEnum
+					.fromResult(rasterEvaluationResult.isSupportedImageFormat());
+				RasterEvaluationResult rasterEvaluationResult1 = new RasterEvaluationResult()
+					.name(matchingExternalReference.get().getName())
+					.crsStatus(crsStatus)
+					.imageFormatStatus(imageFormatStatus);
+				rasterEvaluationResults.add(rasterEvaluationResult1);
+			}
+		});
+		return rasterEvaluationResults;
+	}
+
 	private RulesMetadata rulesMetadata() {
 		if (validatorReport != null && validatorReport.getSemanticValidatorResult() != null) {
 			de.latlon.xplan.validator.semantic.configuration.metadata.RulesMetadata rulesMetadata = validatorReport
diff --git a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/XPlanBoxMediaType.java b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/XPlanMediaType.java
similarity index 98%
rename from xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/XPlanBoxMediaType.java
rename to xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/XPlanMediaType.java
index da9a08c6f2442ebde41ca5939b1aa92f6f74c2b2..327d5aec55b0684898e1b2ba6159eefab79db91d 100644
--- a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/XPlanBoxMediaType.java
+++ b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/XPlanMediaType.java
@@ -25,7 +25,7 @@ import jakarta.ws.rs.core.MediaType;
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
  */
-public class XPlanBoxMediaType {
+public class XPlanMediaType {
 
 	public static final String APPLICATION_ZIP = "application/zip";
 
diff --git a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/config/ApiConfiguration.java b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/config/ApiConfiguration.java
index 985a1424dd59130dfd7fb304073dd45004e02fe7..1fdf4751e4b7b0ddc9135d87341866f265dedd73 100644
--- a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/config/ApiConfiguration.java
+++ b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/config/ApiConfiguration.java
@@ -139,9 +139,11 @@ public abstract class ApiConfiguration {
 	 */
 	protected URI parseUri(Properties properties, String propName) throws ConfigurationException {
 		String property = properties.getProperty(propName);
-		if (property == null || "".equals(property))
+		if (property == null || property.isEmpty())
 			return null;
 		try {
+			if (!property.endsWith("/"))
+				property = property + "/";
 			return new URI(property);
 		}
 		catch (URISyntaxException e) {
diff --git a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/AbstractLink.java b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/AbstractLink.java
index 29caeb95b4b3649535d7bb87ddeaeaf166c1cd77..dafff5dca93163373cd449853701ad848ddc9c6a 100644
--- a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/AbstractLink.java
+++ b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/AbstractLink.java
@@ -20,9 +20,12 @@
  */
 package de.latlon.xplanbox.api.commons.v1.model;
 
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
+
 import java.net.URI;
 import java.util.Objects;
 
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
@@ -46,12 +49,16 @@ public class AbstractLink {
 
 	private @Valid URI href;
 
+	@JsonInclude(NON_NULL)
 	private @Valid String type;
 
+	@JsonInclude(NON_NULL)
 	private @Valid String hreflang;
 
+	@JsonInclude(NON_NULL)
 	private @Valid String title;
 
+	@JsonInclude(NON_NULL)
 	private @Valid Integer length;
 
 	public AbstractLink href(URI href) {
diff --git a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/ExternalReferenceResult.java b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/ExternalReferenceResult.java
index b9bb113ca633b79c71257868f16a4bfe8b305db0..dab78bfdd290be2d407ccb38918e7d1d3c16029d 100644
--- a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/ExternalReferenceResult.java
+++ b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/ExternalReferenceResult.java
@@ -20,10 +20,7 @@
  */
 package de.latlon.xplanbox.api.commons.v1.model;
 
-import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonProperty;
-import de.latlon.xplanbox.api.commons.v2.model.CrsStatusEnum;
-import de.latlon.xplanbox.api.commons.v2.model.ImageFormatStatusEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.xml.bind.annotation.XmlAccessType;
@@ -42,10 +39,6 @@ public class ExternalReferenceResult {
 
 	private @Valid ExternalReferenceStatusEnum status;
 
-	private @Valid @JsonInclude(JsonInclude.Include.NON_NULL) CrsStatusEnum crsStatus;
-
-	private @Valid @JsonInclude(JsonInclude.Include.NON_NULL) ImageFormatStatusEnum imageFormatStatus;
-
 	public void setName(String name) {
 		this.name = name;
 	}
@@ -76,34 +69,4 @@ public class ExternalReferenceResult {
 		return status;
 	}
 
-	public ExternalReferenceResult crsStatus(CrsStatusEnum crsStatus) {
-		this.crsStatus = crsStatus;
-		return this;
-	}
-
-	public void setCrsStatus(@Valid CrsStatusEnum crsStatus) {
-		this.crsStatus = crsStatus;
-	}
-
-	@Schema(example = "SUPPORTED")
-	@JsonProperty("crsStatus")
-	public @Valid CrsStatusEnum getCrsStatus() {
-		return crsStatus;
-	}
-
-	public ExternalReferenceResult imageFormatStatus(ImageFormatStatusEnum imageFormatStatus) {
-		this.imageFormatStatus = imageFormatStatus;
-		return this;
-	}
-
-	public void setImageFormatStatus(@Valid ImageFormatStatusEnum imageFormatStatus) {
-		this.imageFormatStatus = imageFormatStatus;
-	}
-
-	@Schema(example = "SUPPORTED")
-	@JsonProperty("imageFormatStatus")
-	public @Valid ImageFormatStatusEnum getImageFormatStatus() {
-		return imageFormatStatus;
-	}
-
 }
diff --git a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/RasterEvaluationResult.java b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/RasterEvaluationResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..58eaa70a586c508f6830cee2d30964fc14687d5c
--- /dev/null
+++ b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/RasterEvaluationResult.java
@@ -0,0 +1,92 @@
+/*-
+ * #%L
+ * xplan-core-api - Modul zur Gruppierung der Kernmodule
+ * %%
+ * Copyright (C) 2008 - 2024 Freie und Hansestadt Hamburg, developed by lat/lon gesellschaft für raumbezogene Informationssysteme mbH
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * 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%
+ */
+package de.latlon.xplanbox.api.commons.v1.model;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import de.latlon.xplanbox.api.commons.v2.model.CrsStatusEnum;
+import de.latlon.xplanbox.api.commons.v2.model.ImageFormatStatusEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.Valid;
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class RasterEvaluationResult {
+
+	private @Valid String name;
+
+	private @Valid @JsonInclude(JsonInclude.Include.NON_NULL) CrsStatusEnum crsStatus;
+
+	private @Valid @JsonInclude(JsonInclude.Include.NON_NULL) ImageFormatStatusEnum imageFormatStatus;
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public RasterEvaluationResult name(String name) {
+		this.name = name;
+		return this;
+	}
+
+	@Schema(example = "stelling.png")
+	@JsonProperty("name")
+	public String getName() {
+		return name;
+	}
+
+	public RasterEvaluationResult crsStatus(CrsStatusEnum crsStatus) {
+		this.crsStatus = crsStatus;
+		return this;
+	}
+
+	public void setCrsStatus(@Valid CrsStatusEnum crsStatus) {
+		this.crsStatus = crsStatus;
+	}
+
+	@Schema(example = "SUPPORTED")
+	@JsonProperty("crsStatus")
+	public @Valid CrsStatusEnum getCrsStatus() {
+		return crsStatus;
+	}
+
+	public RasterEvaluationResult imageFormatStatus(ImageFormatStatusEnum imageFormatStatus) {
+		this.imageFormatStatus = imageFormatStatus;
+		return this;
+	}
+
+	public void setImageFormatStatus(@Valid ImageFormatStatusEnum imageFormatStatus) {
+		this.imageFormatStatus = imageFormatStatus;
+	}
+
+	@Schema(example = "SUPPORTED")
+	@JsonProperty("imageFormatStatus")
+	public @Valid ImageFormatStatusEnum getImageFormatStatus() {
+		return imageFormatStatus;
+	}
+
+}
diff --git a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/SystemConfig.java b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/SystemConfig.java
index cf4f8a010292cb068e15d1a0b9ce78e445ea8292..419f978bb4dfb9089a6d993c41a6b9da5e180ebc 100644
--- a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/SystemConfig.java
+++ b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/SystemConfig.java
@@ -20,17 +20,18 @@
  */
 package de.latlon.xplanbox.api.commons.v1.model;
 
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import io.swagger.v3.oas.annotations.media.ArraySchema;
-import io.swagger.v3.oas.annotations.media.Schema;
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY;
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
 
-import jakarta.validation.Valid;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 
-import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.v3.oas.annotations.media.ArraySchema;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.Valid;
 
 @jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaJAXRSSpecServerCodegen",
 		date = "2020-08-27T12:32:04.497+02:00[Europe/Berlin]")
@@ -43,7 +44,10 @@ public class SystemConfig {
 	@JsonInclude(NON_EMPTY)
 	private @Valid List<RulesMetadata> profiles = new ArrayList<>();
 
-	private @Valid List<VersionEnum> supportedXPlanGmlVersions = new ArrayList<VersionEnum>();
+	private @Valid List<VersionEnum> supportedXPlanGmlVersions = new ArrayList<>();
+
+	@JsonInclude(NON_NULL)
+	private Boolean skipRasterEvaluation;
 
 	/**
 	 * Version der xPlanBox
@@ -117,6 +121,19 @@ public class SystemConfig {
 		this.supportedXPlanGmlVersions = supportedXPlanGmlVersions;
 	}
 
+	public SystemConfig skipRasterEvaluation(Boolean skipRasterEvaluation) {
+		this.skipRasterEvaluation = skipRasterEvaluation;
+		return this;
+	}
+
+	public Boolean getSkipRasterEvaluation() {
+		return skipRasterEvaluation;
+	}
+
+	public void setSkipRasterEvaluation(Boolean skipRasterEvaluation) {
+		this.skipRasterEvaluation = skipRasterEvaluation;
+	}
+
 	@Override
 	public boolean equals(java.lang.Object o) {
 		if (this == o) {
@@ -129,12 +146,13 @@ public class SystemConfig {
 		return Objects.equals(this.version, systemConfig.version)
 				&& Objects.equals(this.rulesMetadata, systemConfig.rulesMetadata)
 				&& Objects.equals(this.profiles, systemConfig.profiles)
-				&& Objects.equals(this.supportedXPlanGmlVersions, systemConfig.supportedXPlanGmlVersions);
+				&& Objects.equals(this.supportedXPlanGmlVersions, systemConfig.supportedXPlanGmlVersions)
+				&& Objects.equals(this.skipRasterEvaluation, systemConfig.skipRasterEvaluation);
 	}
 
 	@Override
 	public int hashCode() {
-		return Objects.hash(version, rulesMetadata, profiles, supportedXPlanGmlVersions);
+		return Objects.hash(version, rulesMetadata, profiles, supportedXPlanGmlVersions, skipRasterEvaluation);
 	}
 
 	@Override
@@ -146,6 +164,7 @@ public class SystemConfig {
 		sb.append("    rulesMetadata: ").append(toIndentedString(rulesMetadata)).append("\n");
 		sb.append("    profiles: ").append(toIndentedString(profiles)).append("\n");
 		sb.append("    supportedXPlanGmlVersions: ").append(toIndentedString(supportedXPlanGmlVersions)).append("\n");
+		sb.append("    skipRasterEvaluation: ").append(toIndentedString(skipRasterEvaluation)).append("\n");
 		sb.append("}");
 		return sb.toString();
 	}
diff --git a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/ValidationReport.java b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/ValidationReport.java
index c866e368e6a0db455d3a20b649c80bd77ac35623..1ef8c4feb9146ade2ec91aa1d404f34d4754aa9a 100644
--- a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/ValidationReport.java
+++ b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/ValidationReport.java
@@ -20,21 +20,21 @@
  */
 package de.latlon.xplanbox.api.commons.v1.model;
 
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonInclude.Include;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import io.swagger.v3.oas.annotations.media.ArraySchema;
 import io.swagger.v3.oas.annotations.media.Schema;
-
 import jakarta.validation.Valid;
 import jakarta.xml.bind.annotation.XmlAccessType;
 import jakarta.xml.bind.annotation.XmlAccessorType;
 import jakarta.xml.bind.annotation.XmlRootElement;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Objects;
 
 @jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaJAXRSSpecServerCodegen",
 		date = "2020-08-27T12:32:04.497+02:00[Europe/Berlin]")
@@ -62,6 +62,8 @@ public class ValidationReport {
 
 	private @Valid List<ExternalReferenceResult> externalReferencesResult = new ArrayList<>();
 
+	private @Valid List<RasterEvaluationResult> rasterEvaluationResults = new ArrayList<>();
+
 	private @Valid @JsonInclude(Include.NON_NULL) URI wmsUrl;
 
 	private @Valid RulesMetadata rulesMetadata;
@@ -236,6 +238,21 @@ public class ValidationReport {
 		this.externalReferencesResult = externalReferencesResult;
 	}
 
+	/**
+	 **/
+	public ValidationReport rasterEvaluationResults(@Valid List<RasterEvaluationResult> rasterEvaluationResults) {
+		this.rasterEvaluationResults = rasterEvaluationResults;
+		return this;
+	}
+
+	public @Valid List<RasterEvaluationResult> getRasterEvaluationResults() {
+		return rasterEvaluationResults;
+	}
+
+	public void setRasterEvaluationResults(@Valid List<RasterEvaluationResult> rasterEvaluationResults) {
+		this.rasterEvaluationResults = rasterEvaluationResults;
+	}
+
 	/**
 	 * @deprecated XPlanValidatorWMS is deprecated and will be removed in a future version
 	 */
@@ -315,6 +332,7 @@ public class ValidationReport {
 				&& Objects.equals(this.valid, validationReport.valid)
 				&& Objects.equals(this.externalReferences, validationReport.externalReferences)
 				&& Objects.equals(this.externalReferencesResult, validationReport.externalReferencesResult)
+				&& Objects.equals(this.rasterEvaluationResults, validationReport.rasterEvaluationResults)
 				&& Objects.equals(this.wmsUrl, validationReport.wmsUrl)
 				&& Objects.equals(this.rulesMetadata, validationReport.rulesMetadata)
 				&& Objects.equals(this.validationResult, validationReport.validationResult);
@@ -322,8 +340,8 @@ public class ValidationReport {
 
 	@Override
 	public int hashCode() {
-		return Objects.hash(filename, name, documentSummary, version, bbox, date, valid, externalReferences, wmsUrl,
-				rulesMetadata, validationResult);
+		return Objects.hash(filename, name, documentSummary, version, bbox, date, valid, externalReferences,
+				rasterEvaluationResults, wmsUrl, rulesMetadata, validationResult);
 	}
 
 	@Override
@@ -340,6 +358,7 @@ public class ValidationReport {
 		sb.append("    valid: ").append(toIndentedString(valid)).append("\n");
 		sb.append("    externalReferences: ").append(toIndentedString(externalReferences)).append("\n");
 		sb.append("    externalReferencesResult: ").append(toIndentedString(externalReferencesResult)).append("\n");
+		sb.append("    rasterEvaluationResults: ").append(toIndentedString(rasterEvaluationResults)).append("\n");
 		sb.append("    wmsUrl: ").append(toIndentedString(wmsUrl)).append("\n");
 		sb.append("    rulesMetadata: ").append(toIndentedString(rulesMetadata)).append("\n");
 		sb.append("    validationResult: ").append(toIndentedString(validationResult)).append("\n");
diff --git a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v2/model/ResponseLink.java b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v2/model/ResponseLink.java
index d086270c4e78906f6a104a8624d8793191d65d3f..88d87b3c4c8256965d881f52e09799f5cf63f5ed 100644
--- a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v2/model/ResponseLink.java
+++ b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v2/model/ResponseLink.java
@@ -20,15 +20,20 @@
  */
 package de.latlon.xplanbox.api.commons.v2.model;
 
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
+
+import java.net.URI;
 import java.util.Date;
 import java.util.Objects;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonValue;
 import de.latlon.xplanbox.api.commons.v1.model.AbstractLink;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
 import jakarta.xml.bind.annotation.XmlAccessType;
 import jakarta.xml.bind.annotation.XmlAccessorType;
 import jakarta.xml.bind.annotation.XmlRootElement;
@@ -80,6 +85,10 @@ public class ResponseLink extends AbstractLink {
 
 	private @Valid RelEnum rel;
 
+	@JsonInclude(NON_NULL)
+	private @Valid URI schema;
+
+	@JsonInclude(NON_NULL)
 	private Date expirationTime;
 
 	public ResponseLink rel(RelEnum rel) {
@@ -97,6 +106,22 @@ public class ResponseLink extends AbstractLink {
 		this.rel = rel;
 	}
 
+	public ResponseLink schema(URI schema) {
+		this.schema = schema;
+		return this;
+	}
+
+	@Schema(example = "https://xplanbox.lat-lon.de/xmanager/api/v1#/components/schemas/ValidationReport")
+	@JsonProperty("schema")
+	@NotNull
+	public URI getSchema() {
+		return schema;
+	}
+
+	public void setSchema(URI schema) {
+		this.schema = schema;
+	}
+
 	public Date getExpirationTime() {
 		return expirationTime;
 	}
diff --git a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v2/model/StatusNotification.java b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v2/model/StatusNotification.java
index 69262f1552825002c634d621e626bb53e4ee61a8..3128057924f07d91f4038b5b8f644f4560fd1a5a 100644
--- a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v2/model/StatusNotification.java
+++ b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v2/model/StatusNotification.java
@@ -1,41 +1,28 @@
 package de.latlon.xplanbox.api.commons.v2.model;
 
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY;
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
+
+import java.util.ArrayList;
 import java.util.List;
 
+import com.fasterxml.jackson.annotation.JsonInclude;
+
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
  * @since 8.0
  */
-public class StatusNotification {
-
-	private StatusEnum status;
+public abstract class StatusNotification {
 
+	@JsonInclude(NON_NULL)
 	private String errorMsg;
 
-	private List<String> importedPlanIds;
-
-	private List<ResponseLink> links;
+	@JsonInclude(NON_EMPTY)
+	private List<ResponseLink> links = new ArrayList<>();
 
 	public StatusNotification() {
 	}
 
-	public StatusNotification(StatusEnum status) {
-		this.status = status;
-	}
-
-	public StatusEnum getStatus() {
-		return status;
-	}
-
-	public void setStatus(StatusEnum status) {
-		this.status = status;
-	}
-
-	public StatusNotification status(StatusEnum status) {
-		this.status = status;
-		return this;
-	}
-
 	public String getErrorMsg() {
 		return errorMsg;
 	}
@@ -67,17 +54,10 @@ public class StatusNotification {
 		return this;
 	}
 
-	public List<String> getImportedPlanIds() {
-		return importedPlanIds;
-	}
-
-	public void setImportedPlanIds(List<String> importedPlanIds) {
-		this.importedPlanIds = importedPlanIds;
-	}
-
-	public StatusNotification importedPlanIds(List<String> importedPlanIds) {
-		this.importedPlanIds = importedPlanIds;
-		return this;
+	public void addLink(ResponseLink link) {
+		if (this.links == null)
+			this.links = new ArrayList<>();
+		this.links.add(link);
 	}
 
 }
diff --git a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v2/model/SystemConfig.java b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v2/model/SystemConfig.java
index 4dd80d21807cfccf216ee14b20cc67a611b6e7ab..586282dd4029657ee511b4d089ea55aa35ea1e70 100644
--- a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v2/model/SystemConfig.java
+++ b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v2/model/SystemConfig.java
@@ -47,6 +47,12 @@ public class SystemConfig {
 
 	private @Valid List<VersionEnum> supportedXPlanGmlVersions = new ArrayList<VersionEnum>();
 
+	@JsonInclude(NON_NULL)
+	private Boolean skipRasterEvaluation;
+
+	/**
+	 * Version der xPlanBox
+	 **/
 	public SystemConfig version(String version) {
 		this.version = version;
 		return this;
@@ -95,6 +101,19 @@ public class SystemConfig {
 		this.supportedXPlanGmlVersions = supportedXPlanGmlVersions;
 	}
 
+	public SystemConfig skipRasterEvaluation(Boolean skipRasterEvaluation) {
+		this.skipRasterEvaluation = skipRasterEvaluation;
+		return this;
+	}
+
+	public Boolean getSkipRasterEvaluation() {
+		return skipRasterEvaluation;
+	}
+
+	public void setSkipRasterEvaluation(Boolean skipRasterEvaluation) {
+		this.skipRasterEvaluation = skipRasterEvaluation;
+	}
+
 	@Override
 	public boolean equals(Object o) {
 		if (this == o) {
@@ -106,12 +125,13 @@ public class SystemConfig {
 		SystemConfig systemConfig = (SystemConfig) o;
 		return Objects.equals(this.version, systemConfig.version)
 				&& Objects.equals(this.profiles, systemConfig.profiles)
-				&& Objects.equals(this.supportedXPlanGmlVersions, systemConfig.supportedXPlanGmlVersions);
+				&& Objects.equals(this.supportedXPlanGmlVersions, systemConfig.supportedXPlanGmlVersions)
+				&& Objects.equals(this.skipRasterEvaluation, systemConfig.skipRasterEvaluation);
 	}
 
 	@Override
 	public int hashCode() {
-		return Objects.hash(version, profiles, supportedXPlanGmlVersions);
+		return Objects.hash(version, profiles, supportedXPlanGmlVersions, skipRasterEvaluation);
 	}
 
 	@Override
@@ -122,6 +142,7 @@ public class SystemConfig {
 		sb.append("    version: ").append(toIndentedString(version)).append("\n");
 		sb.append("    profiles: ").append(toIndentedString(profiles)).append("\n");
 		sb.append("    supportedXPlanGmlVersions: ").append(toIndentedString(supportedXPlanGmlVersions)).append("\n");
+		sb.append("    skipRasterEvaluation: ").append(toIndentedString(skipRasterEvaluation)).append("\n");
 		sb.append("}");
 		return sb.toString();
 	}
diff --git a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v2/model/ValidationReport.java b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v2/model/ValidationReport.java
index b872e66c7444c226e481c82de3e2d47f46c907c2..c2dfbc96df458c274400c9c8136e90fcbbf75ab1 100644
--- a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v2/model/ValidationReport.java
+++ b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v2/model/ValidationReport.java
@@ -32,6 +32,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 import de.latlon.xplanbox.api.commons.v1.model.DocumentSummary;
 import de.latlon.xplanbox.api.commons.v1.model.ExternalReferenceResult;
 import de.latlon.xplanbox.api.commons.v1.model.PlanInfoBbox;
+import de.latlon.xplanbox.api.commons.v1.model.RasterEvaluationResult;
 import de.latlon.xplanbox.api.commons.v1.model.RulesMetadata;
 import de.latlon.xplanbox.api.commons.v1.model.VersionEnum;
 import io.swagger.v3.oas.annotations.media.ArraySchema;
@@ -67,6 +68,8 @@ public class ValidationReport {
 
 	private @Valid List<ExternalReferenceResult> externalReferencesResult = new ArrayList<>();
 
+	private @Valid List<RasterEvaluationResult> rasterEvaluationResults = new ArrayList<>();
+
 	private @Valid @JsonInclude(Include.NON_NULL) URI wmsUrl;
 
 	private @Valid RulesMetadata rulesMetadata;
@@ -206,6 +209,19 @@ public class ValidationReport {
 		this.externalReferencesResult = externalReferencesResult;
 	}
 
+	public ValidationReport rasterEvaluationResults(@Valid List<RasterEvaluationResult> rasterEvaluationResults) {
+		this.rasterEvaluationResults = rasterEvaluationResults;
+		return this;
+	}
+
+	public @Valid List<RasterEvaluationResult> getRasterEvaluationResults() {
+		return rasterEvaluationResults;
+	}
+
+	public void setRasterEvaluationResults(@Valid List<RasterEvaluationResult> rasterEvaluationResults) {
+		this.rasterEvaluationResults = rasterEvaluationResults;
+	}
+
 	/**
 	 * @deprecated XPlanValidatorWMS is deprecated and will be removed in a future version
 	 */
@@ -280,6 +296,7 @@ public class ValidationReport {
 				&& Objects.equals(this.bbox, validationReport.bbox) && Objects.equals(this.date, validationReport.date)
 				&& Objects.equals(this.valid, validationReport.valid)
 				&& Objects.equals(this.externalReferencesResult, validationReport.externalReferencesResult)
+				&& Objects.equals(this.rasterEvaluationResults, validationReport.rasterEvaluationResults)
 				&& Objects.equals(this.wmsUrl, validationReport.wmsUrl)
 				&& Objects.equals(this.rulesMetadata, validationReport.rulesMetadata)
 				&& Objects.equals(this.validationResult, validationReport.validationResult);
@@ -288,7 +305,7 @@ public class ValidationReport {
 	@Override
 	public int hashCode() {
 		return Objects.hash(filename, name, documentSummary, version, bbox, date, valid, externalReferencesResult,
-				wmsUrl, rulesMetadata, validationResult);
+				rasterEvaluationResults, wmsUrl, rulesMetadata, validationResult);
 	}
 
 	@Override
@@ -304,6 +321,7 @@ public class ValidationReport {
 		sb.append("    date: ").append(toIndentedString(date)).append("\n");
 		sb.append("    valid: ").append(toIndentedString(valid)).append("\n");
 		sb.append("    externalReferencesResult: ").append(toIndentedString(externalReferencesResult)).append("\n");
+		sb.append("    rasterEvaluationResults: ").append(toIndentedString(rasterEvaluationResults)).append("\n");
 		sb.append("    wmsUrl: ").append(toIndentedString(wmsUrl)).append("\n");
 		sb.append("    rulesMetadata: ").append(toIndentedString(rulesMetadata)).append("\n");
 		sb.append("    validationResult: ").append(toIndentedString(validationResult)).append("\n");
diff --git a/xplan-core/xplan-core-api/src/test/java/de/latlon/xplanbox/api/commons/ValidationReportBuilderTest.java b/xplan-core/xplan-core-api/src/test/java/de/latlon/xplanbox/api/commons/ValidationReportBuilderTest.java
index 15864cb3d624efcac37b6fb7ae40ee5070eecb96..63204bee2e22f09f3ad07c89cd4b04bfb6d33bac 100644
--- a/xplan-core/xplan-core-api/src/test/java/de/latlon/xplanbox/api/commons/ValidationReportBuilderTest.java
+++ b/xplan-core/xplan-core-api/src/test/java/de/latlon/xplanbox/api/commons/ValidationReportBuilderTest.java
@@ -21,19 +21,22 @@
 package de.latlon.xplanbox.api.commons;
 
 import static de.latlon.xplan.commons.XPlanVersion.XPLAN_52;
+import static de.latlon.xplan.validator.report.reference.ExternalReferenceStatus.AVAILABLE;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.mockito.Mockito.when;
 
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.Collections;
 
-import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
-
+import de.latlon.xplan.manager.web.shared.RasterEvaluationResult;
 import de.latlon.xplan.validator.report.ValidatorReport;
+import de.latlon.xplan.validator.report.reference.ExternalReferenceReport;
 import de.latlon.xplanbox.api.commons.v1.model.ValidationReport;
 import de.latlon.xplanbox.api.commons.v1.model.VersionEnum;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
 
 /**
  * @author <a href="mailto:friebe@lat-lon.de">Torsten Friebe</a>
@@ -72,6 +75,38 @@ class ValidationReportBuilderTest {
 		assertThat(report.getWmsUrl()).isNotNull();
 	}
 
+	@Test
+	void verifyThat_Builder_AddRasterEvaluationResult_v1() throws URISyntaxException {
+		ValidatorReport sourceReport = Mockito.mock(ValidatorReport.class);
+		when(sourceReport.getExternalReferenceReport())
+			.thenReturn(new ExternalReferenceReport(Collections.singletonMap("test.png", AVAILABLE)));
+		when(sourceReport.getRasterEvaluationResults()).thenReturn(Collections
+			.singletonList(new RasterEvaluationResult("test.png", "EPSG:25832", "EPSG:25832", true, true, true)));
+		ValidationReport validationReport = new ValidationReportBuilder().validatorReport(sourceReport)
+			.filename("test.xml")
+			.wmsUrl(new URI("file:///no/real/file/name"))
+			.build();
+		assertThat(validationReport.getExternalReferences().size()).isEqualTo(1);
+		assertThat(validationReport.getExternalReferencesResult().size()).isEqualTo(1);
+		assertThat(validationReport.getRasterEvaluationResults().size()).isEqualTo(1);
+	}
+
+	@Test
+	void verifyThat_Builder_AddRasterEvaluationResult_v2() throws URISyntaxException {
+		ValidatorReport sourceReport = Mockito.mock(ValidatorReport.class);
+		when(sourceReport.getExternalReferenceReport())
+			.thenReturn(new ExternalReferenceReport(Collections.singletonMap("test.png", AVAILABLE)));
+		when(sourceReport.getRasterEvaluationResults()).thenReturn(Collections
+			.singletonList(new RasterEvaluationResult("test.png", "EPSG:25832", "EPSG:25832", true, true, true)));
+		de.latlon.xplanbox.api.commons.v2.model.ValidationReport validationReport = new ValidationReportBuilder()
+			.validatorReport(sourceReport)
+			.filename("test.xml")
+			.wmsUrl(new URI("file:///no/real/file/name"))
+			.buildV2();
+		assertThat(validationReport.getExternalReferencesResult().size()).isEqualTo(1);
+		assertThat(validationReport.getRasterEvaluationResults().size()).isEqualTo(1);
+	}
+
 	@Test
 	void verifyThat_Builder_ReturnsCompleteInstance() throws URISyntaxException {
 		ValidatorReport sourceReport = Mockito.mock(ValidatorReport.class);
diff --git a/xplan-core/xplan-core-api/src/test/java/de/latlon/xplanbox/api/commons/v2/model/ValidationReportTest.java b/xplan-core/xplan-core-api/src/test/java/de/latlon/xplanbox/api/commons/v2/model/ValidationReportTest.java
index b08381c606264ac1ca11b983ca72f7e1bb1b08a1..ea7a3e6b58d33641d35119b371dd76c2183517f9 100644
--- a/xplan-core/xplan-core-api/src/test/java/de/latlon/xplanbox/api/commons/v2/model/ValidationReportTest.java
+++ b/xplan-core/xplan-core-api/src/test/java/de/latlon/xplanbox/api/commons/v2/model/ValidationReportTest.java
@@ -18,6 +18,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
 import de.latlon.xplanbox.api.commons.ObjectMapperContextResolver;
 import de.latlon.xplanbox.api.commons.v1.model.ExternalReferenceResult;
+import de.latlon.xplanbox.api.commons.v1.model.RasterEvaluationResult;
 import org.junit.jupiter.api.Test;
 
 /**
@@ -28,7 +29,8 @@ public class ValidationReportTest {
 	@Test
 	void verifyThat_ReportCanBeSerialized() throws URISyntaxException, IOException {
 		ExternalReferenceResult externalReferenceResult = new ExternalReferenceResult().name("test.png")
-			.status(AVAILABLE)
+			.status(AVAILABLE);
+		RasterEvaluationResult rasterEvaluationResult = new RasterEvaluationResult().name("test.png")
 			.crsStatus(MISSING)
 			.imageFormatStatus(UNSUPPORTED);
 		ValidationReport validationReport = new ValidationReport().date(LocalDateTime.of(2024, JULY, 31, 9, 55))
@@ -38,7 +40,8 @@ public class ValidationReportTest {
 			.status("valid")
 			.filename("text.xml")
 			.wmsUrl(new URI("file:///no/real/file/name"))
-			.externalReferencesResult(Collections.singletonList(externalReferenceResult));
+			.externalReferencesResult(Collections.singletonList(externalReferenceResult))
+			.rasterEvaluationResults(Collections.singletonList(rasterEvaluationResult));
 
 		ByteArrayOutputStream bos = new ByteArrayOutputStream();
 		ObjectMapper objectMapper = new ObjectMapperContextResolver().getContext(ValidationReport.class);
diff --git a/xplan-core/xplan-core-commons/pom.xml b/xplan-core/xplan-core-commons/pom.xml
index 5c3398cd8b6b8adc361ea6bce6e095d72b48c363..28dfca60d02cadf274d4ee2e48c351f64d34bf29 100644
--- a/xplan-core/xplan-core-commons/pom.xml
+++ b/xplan-core/xplan-core-commons/pom.xml
@@ -120,6 +120,10 @@
       <groupId>com.amazonaws</groupId>
       <artifactId>aws-java-sdk-s3</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context</artifactId>
+    </dependency>
   </dependencies>
 
 </project>
\ No newline at end of file
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3ReadOnlyContext.java b/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/config/AmazonS3ReadOnlyContext.java
similarity index 98%
rename from xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3ReadOnlyContext.java
rename to xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/config/AmazonS3ReadOnlyContext.java
index 23d853490a59cada1027eb35547edf540300d9d1..895270dd2801434e11cacce67b2fd6414ffa269a 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3ReadOnlyContext.java
+++ b/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/config/AmazonS3ReadOnlyContext.java
@@ -18,7 +18,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  * #L%
  */
-package de.latlon.xplan.manager.storage.s3.config;
+package de.latlon.xplan.commons.s3.config;
 
 import com.amazonaws.auth.AWSCredentials;
 import com.amazonaws.auth.AWSStaticCredentialsProvider;
diff --git a/xplan-core/xplan-core-manager-db/src/main/java/de/latlon/xplan/core/manager/db/config/JpaContext.java b/xplan-core/xplan-core-manager-db/src/main/java/de/latlon/xplan/core/manager/db/config/JpaContext.java
index 308b3b009369e19e68afc8a5e1d890e8c01eb2a6..12dcd392bd4f0b88d44d599cc4cb0b587b7bbd9f 100644
--- a/xplan-core/xplan-core-manager-db/src/main/java/de/latlon/xplan/core/manager/db/config/JpaContext.java
+++ b/xplan-core/xplan-core-manager-db/src/main/java/de/latlon/xplan/core/manager/db/config/JpaContext.java
@@ -20,22 +20,21 @@
  */
 package de.latlon.xplan.core.manager.db.config;
 
-import de.latlon.xplan.core.manager.db.DatasourceWrapper;
+import javax.sql.DataSource;
+import java.sql.SQLException;
 
-import org.hibernate.jpa.HibernatePersistenceProvider;
+import de.latlon.xplan.core.manager.db.DatasourceWrapper;
+import jakarta.persistence.EntityManagerFactory;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
 import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
 import org.springframework.orm.jpa.JpaTransactionManager;
 import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
 import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
 import org.springframework.transaction.annotation.EnableTransactionManagement;
 
-import jakarta.persistence.EntityManagerFactory;
-import javax.sql.DataSource;
-import java.sql.SQLException;
-
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
  * @since 7.0
@@ -47,6 +46,7 @@ import java.sql.SQLException;
 public class JpaContext {
 
 	@Bean
+	@Profile("!test")
 	public DataSource dataSource(DatasourceWrapper datasourceWrapper) throws SQLException {
 		return datasourceWrapper.retrieveDataSource();
 	}
@@ -64,6 +64,7 @@ public class JpaContext {
 	}
 
 	@Bean
+	@Profile("!test")
 	public HibernateJpaVendorAdapter jpaVendorAdapter() {
 		HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
 		return vendorAdapter;
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3TransactionalContext.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3TransactionalContext.java
index 18227e5405fb45ff8705eea28841c3ddd1d8d2fc..1d05b3a212e66813e80165730d267b293aa3e9af 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3TransactionalContext.java
+++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3TransactionalContext.java
@@ -22,6 +22,7 @@ package de.latlon.xplan.manager.storage.s3.config;
 
 import com.amazonaws.services.s3.AmazonS3;
 import de.latlon.xplan.commons.s3.S3Storage;
+import de.latlon.xplan.commons.s3.config.AmazonS3ReadOnlyContext;
 import de.latlon.xplan.manager.storage.StorageCleanUpManager;
 import de.latlon.xplan.manager.storage.s3.S3StorageCleanUpManager;
 import org.springframework.beans.factory.annotation.Value;
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 5feb9fe096a4e816d141d39dbb84dbc15c476174..fbc466c4e2b8ddadbc5592043ee460c2bfd8e475 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,8 +26,8 @@ package de.latlon.core.validator.events;
  */
 public interface EventSender {
 
-	void sendEvent(XPlanboxInternalEvent e);
+	void sendEvent(XPlanInternalEvent e);
 
-	void sendPublicEvent(XPlanboxPublicEvent e);
+	void sendPublicEvent(XPlanPublicEvent e);
 
 }
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 696f00214f145122a58b9852963e4a8aaff0e2b7..152845b9aa61e84808680fd6483f1b1e707f1100 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
@@ -60,8 +60,8 @@ class RabbitEventSender implements EventSender {
 	}
 
 	@Override
-	public void sendEvent(XPlanboxInternalEvent event) {
-		if (event instanceof XPlanboxInternalTaskEvent) {
+	public void sendEvent(XPlanInternalEvent event) {
+		if (event instanceof XPlanInternalTaskEvent) {
 			String workQueueName = taskClass2QueueName.get(event.getClass());
 			if (workQueueName == null) {
 				LOG.error("Ignoring task: no queue configured to send event to ({})", event);
@@ -79,7 +79,7 @@ class RabbitEventSender implements EventSender {
 	}
 
 	@Override
-	public void sendPublicEvent(XPlanboxPublicEvent event) {
+	public void sendPublicEvent(XPlanPublicEvent event) {
 		LOG.info("Sending fanout public event: {}", event);
 		rabbitTemplate.convertAndSend(publicFanoutExchangeName, "xplanbox", event);
 	}
diff --git a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationFinishedEvent.java b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationFinishedEvent.java
index b4cb999c16b497506263850be50aa512353f14da..1c012aa09ab197395fc98518d3f3895affad536f 100644
--- a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationFinishedEvent.java
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationFinishedEvent.java
@@ -24,7 +24,7 @@ package de.latlon.core.validator.events;
  * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
  * @since 8.0
  */
-public class ValidationFinishedEvent extends XPlanboxInternalFanoutEvent {
+public class ValidationFinishedEvent extends XPlanInternalFanoutEvent {
 
 	private String uuid;
 
diff --git a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationRequestedEvent.java b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationRequestedEvent.java
index 862e0055859d05fcb2868e174a6d88c2346ae2df..cc2dadbf110761210b39de4aab56a53f859d2c32 100644
--- a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationRequestedEvent.java
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationRequestedEvent.java
@@ -6,7 +6,7 @@ import de.latlon.xplan.validator.web.shared.ValidationSettings;
  * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
  * @since 7.2
  */
-public class ValidationRequestedEvent extends XPlanboxInternalTaskEvent {
+public class ValidationRequestedEvent extends XPlanInternalTaskEvent {
 
 	public enum MediaType {
 
diff --git a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxInternalEvent.java b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanInternalEvent.java
similarity index 61%
rename from xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxInternalEvent.java
rename to xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanInternalEvent.java
index b162e1b17eb82dee295db3e5e8d572f22b21503c..7baa33983412e62b0c3b9bf6189682fd73fddd5a 100644
--- a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxInternalEvent.java
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanInternalEvent.java
@@ -6,6 +6,6 @@ package de.latlon.core.validator.events;
  * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
  * @since 8.0
  */
-public sealed interface XPlanboxInternalEvent permits XPlanboxInternalFanoutEvent, XPlanboxInternalTaskEvent {
+public sealed interface XPlanInternalEvent permits XPlanInternalFanoutEvent, XPlanInternalTaskEvent {
 
 }
diff --git a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxInternalFanoutEvent.java b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanInternalFanoutEvent.java
similarity index 67%
rename from xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxInternalFanoutEvent.java
rename to xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanInternalFanoutEvent.java
index a05b1dc6a3fad64e4cde530fe1a910b7b5ace718..9af80eb6045ef1678c81d4eb62034e03960f110d 100644
--- a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxInternalFanoutEvent.java
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanInternalFanoutEvent.java
@@ -6,6 +6,6 @@ package de.latlon.core.validator.events;
  * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
  * @since 8.0
  */
-public non-sealed class XPlanboxInternalFanoutEvent implements XPlanboxInternalEvent {
+public non-sealed class XPlanInternalFanoutEvent implements XPlanInternalEvent {
 
 }
diff --git a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxInternalTaskEvent.java b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanInternalTaskEvent.java
similarity index 67%
rename from xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxInternalTaskEvent.java
rename to xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanInternalTaskEvent.java
index 001926cde69f8cb84c6baedf53d71026a806b404..bbeb6402d4193d528754f67a4e2971ee16caadde 100644
--- a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxInternalTaskEvent.java
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanInternalTaskEvent.java
@@ -6,6 +6,6 @@ package de.latlon.core.validator.events;
  * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
  * @since 8.0
  */
-public non-sealed class XPlanboxInternalTaskEvent implements XPlanboxInternalEvent {
+public non-sealed class XPlanInternalTaskEvent implements XPlanInternalEvent {
 
 }
diff --git a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxPublicEvent.java b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanPublicEvent.java
similarity index 82%
rename from xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxPublicEvent.java
rename to xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanPublicEvent.java
index bed8dedce39e61ba8f597cea2ed9f89015aa54b5..382e21d3db6dd6040202d5b9a60055d113ab717a 100644
--- a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxPublicEvent.java
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanPublicEvent.java
@@ -6,6 +6,6 @@ package de.latlon.core.validator.events;
  * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
  * @since 8.0
  */
-public interface XPlanboxPublicEvent {
+public interface XPlanPublicEvent {
 
 }
diff --git a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/planimport/ImportFinishedEvent.java b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/planimport/ImportFinishedEvent.java
index 9f186176842a5a6aecbd49e3014c1cad7a6ab894..dab0cfd358d4b17b824f0477daffff6f452550c6 100644
--- a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/planimport/ImportFinishedEvent.java
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/planimport/ImportFinishedEvent.java
@@ -20,13 +20,13 @@
  */
 package de.latlon.core.validator.events.planimport;
 
-import de.latlon.core.validator.events.XPlanboxInternalFanoutEvent;
+import de.latlon.core.validator.events.XPlanInternalFanoutEvent;
 
 /**
  * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
  * @since 8.0
  */
-public class ImportFinishedEvent extends XPlanboxInternalFanoutEvent {
+public class ImportFinishedEvent extends XPlanInternalFanoutEvent {
 
 	private String uuid;
 
diff --git a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/planimport/ImportRequestedEvent.java b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/planimport/ImportRequestedEvent.java
index 276e21ce1aa023fff2471ed94b11dda17530a1ce..472e40c412a5d518896cfd82120d9b3d5202661a 100644
--- a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/planimport/ImportRequestedEvent.java
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/planimport/ImportRequestedEvent.java
@@ -21,13 +21,13 @@
 package de.latlon.core.validator.events.planimport;
 
 import de.latlon.core.validator.events.ValidationRequestedEvent;
-import de.latlon.core.validator.events.XPlanboxInternalTaskEvent;
+import de.latlon.core.validator.events.XPlanInternalTaskEvent;
 
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz</a>
  * @since 8.0
  */
-public class ImportRequestedEvent extends XPlanboxInternalTaskEvent {
+public class ImportRequestedEvent extends XPlanInternalTaskEvent {
 
 	public enum VALIDATION_RESULT {
 
diff --git a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/v1/XPlanboxPublicV1Event.java b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/v1/XPlanPublicV1Event.java
similarity index 78%
rename from xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/v1/XPlanboxPublicV1Event.java
rename to xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/v1/XPlanPublicV1Event.java
index 558c95febf6c5542673a21452bab811d24df0539..c295c1af3d6b7a291027d3f4ff89e92eafd70886 100644
--- a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/v1/XPlanboxPublicV1Event.java
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/v1/XPlanPublicV1Event.java
@@ -2,7 +2,7 @@ package de.latlon.core.validator.events.v1;
 
 import java.util.Objects;
 
-import de.latlon.core.validator.events.XPlanboxPublicEvent;
+import de.latlon.core.validator.events.XPlanPublicEvent;
 
 /**
  * V1 public event.
@@ -10,9 +10,9 @@ import de.latlon.core.validator.events.XPlanboxPublicEvent;
  * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
  * @since 8.0
  */
-public class XPlanboxPublicV1Event implements XPlanboxPublicEvent {
+public class XPlanPublicV1Event implements XPlanPublicEvent {
 
-	public static enum EventType {
+	public enum EventType {
 
 		VALIDATION_STARTED, VALIDATION_FINISHED, IMPORT_STARTED, IMPORT_FINISHED
 
@@ -26,11 +26,11 @@ public class XPlanboxPublicV1Event implements XPlanboxPublicEvent {
 
 	private String message;
 
-	public XPlanboxPublicV1Event() {
+	public XPlanPublicV1Event() {
 
 	}
 
-	public XPlanboxPublicV1Event(EventType eventType, String uuid, String message) {
+	public XPlanPublicV1Event(EventType eventType, String uuid, String message) {
 		this.eventType = eventType;
 		this.uuid = uuid;
 		this.message = message;
@@ -65,7 +65,7 @@ public class XPlanboxPublicV1Event implements XPlanboxPublicEvent {
 			return false;
 		if (getClass() != obj.getClass())
 			return false;
-		XPlanboxPublicV1Event other = (XPlanboxPublicV1Event) obj;
+		XPlanPublicV1Event other = (XPlanPublicV1Event) obj;
 		return Objects.equals(apiVersion, other.apiVersion) && eventType == other.eventType
 				&& Objects.equals(message, other.message) && Objects.equals(uuid, other.uuid);
 	}
diff --git a/xplan-core/xplan-core-validator-events/src/test/java/de/latlon/core/validator/events/v1/XPlanboxPublicV1EventTest.java b/xplan-core/xplan-core-validator-events/src/test/java/de/latlon/core/validator/events/v1/XPlanPublicV1EventTest.java
similarity index 74%
rename from xplan-core/xplan-core-validator-events/src/test/java/de/latlon/core/validator/events/v1/XPlanboxPublicV1EventTest.java
rename to xplan-core/xplan-core-validator-events/src/test/java/de/latlon/core/validator/events/v1/XPlanPublicV1EventTest.java
index c90b8688cbad97435c9b141582890173316326d7..1d698f8805df874ec320b59f4c18776e1a0eb415 100644
--- a/xplan-core/xplan-core-validator-events/src/test/java/de/latlon/core/validator/events/v1/XPlanboxPublicV1EventTest.java
+++ b/xplan-core/xplan-core-validator-events/src/test/java/de/latlon/core/validator/events/v1/XPlanPublicV1EventTest.java
@@ -3,19 +3,18 @@ package de.latlon.core.validator.events.v1;
 import static org.assertj.core.api.Assertions.assertThat;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
-import de.latlon.core.validator.events.v1.XPlanboxPublicV1Event.EventType;
+import de.latlon.core.validator.events.v1.XPlanPublicV1Event.EventType;
 import org.junit.jupiter.api.Test;
 
 /**
  * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
  * @since 8.0
  */
-class XPlanboxPublicV1EventTest {
+class XPlanPublicV1EventTest {
 
 	@Test
 	void jsonSerializeValidationStarted() throws Exception {
-		XPlanboxPublicV1Event event = new XPlanboxPublicV1Event(EventType.VALIDATION_STARTED, "uuid1",
-				"start validation");
+		XPlanPublicV1Event event = new XPlanPublicV1Event(EventType.VALIDATION_STARTED, "uuid1", "start validation");
 
 		ObjectMapper mapper = new ObjectMapper();
 		String json = mapper.writeValueAsString(event);
@@ -27,8 +26,7 @@ class XPlanboxPublicV1EventTest {
 
 	@Test
 	void jsonSerializeValidationFinished() throws Exception {
-		XPlanboxPublicV1Event event = new XPlanboxPublicV1Event(EventType.VALIDATION_FINISHED, "uuid1",
-				"end validation");
+		XPlanPublicV1Event event = new XPlanPublicV1Event(EventType.VALIDATION_FINISHED, "uuid1", "end validation");
 
 		ObjectMapper mapper = new ObjectMapper();
 		String json = mapper.writeValueAsString(event);
@@ -40,7 +38,7 @@ class XPlanboxPublicV1EventTest {
 
 	@Test
 	void jsonSerializeImportStart() throws Exception {
-		XPlanboxPublicV1Event event = new XPlanboxPublicV1Event(EventType.IMPORT_STARTED, "uuid1", "start import");
+		XPlanPublicV1Event event = new XPlanPublicV1Event(EventType.IMPORT_STARTED, "uuid1", "start import");
 
 		ObjectMapper mapper = new ObjectMapper();
 		String json = mapper.writeValueAsString(event);
@@ -52,7 +50,7 @@ class XPlanboxPublicV1EventTest {
 
 	@Test
 	void jsonSerializeImportFinished() throws Exception {
-		XPlanboxPublicV1Event event = new XPlanboxPublicV1Event(EventType.IMPORT_FINISHED, "uuid1", "end import");
+		XPlanPublicV1Event event = new XPlanPublicV1Event(EventType.IMPORT_FINISHED, "uuid1", "end import");
 
 		ObjectMapper mapper = new ObjectMapper();
 		String json = mapper.writeValueAsString(event);
diff --git a/xplan-database/xplan-database-docker/Dockerfile b/xplan-database/xplan-database-docker/Dockerfile
index 8ba67aec8cecd8a22b1d853eedaaf3751712a3c9..5ab9869b9f5780e11d73d2c8c16cf119c85d825e 100644
--- a/xplan-database/xplan-database-docker/Dockerfile
+++ b/xplan-database/xplan-database-docker/Dockerfile
@@ -1,5 +1,5 @@
-# latest postgis/postgis:14-3.4 on 13.05.24
-FROM postgis/postgis@sha256:c440053789c149a953adb609dc1c47bcdb97e792ef7018e82f7d592933e46fed
+# latest postgis/postgis:14-3.4 on 04.09.24
+FROM postgis/postgis@sha256:cf36b0ba61eeafbcbc45a419c8ed014dd93f073fc2e9041e0fefa121fd4384a9
 
 ARG BUILD_DATE=?
 ARG DOCKER_IMAGE_NAME=?
diff --git a/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/config/S3DocumentContext.java b/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/config/S3DocumentContext.java
index 528ec6eeedf193baaa5351a38e6234fe59a42e93..c31cef8bf9143a42ff5a9d1f6ea93a5ecdc369eb 100644
--- a/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/config/S3DocumentContext.java
+++ b/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/config/S3DocumentContext.java
@@ -24,7 +24,7 @@ import static org.slf4j.LoggerFactory.getLogger;
 
 import com.amazonaws.services.s3.AmazonS3;
 import de.latlon.xplan.commons.s3.S3Storage;
-import de.latlon.xplan.manager.storage.s3.config.AmazonS3ReadOnlyContext;
+import de.latlon.xplan.commons.s3.config.AmazonS3ReadOnlyContext;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
diff --git a/xplan-gateway/.maven-dockerinclude b/xplan-gateway/.maven-dockerinclude
new file mode 100644
index 0000000000000000000000000000000000000000..fb59421b161353180fcfc72c9e17db8c759869c1
--- /dev/null
+++ b/xplan-gateway/.maven-dockerinclude
@@ -0,0 +1,2 @@
+run.sh
+target/*-repackaged.war
\ No newline at end of file
diff --git a/xplan-gateway/Dockerfile b/xplan-gateway/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..11eec26a4009ea4569513074a0ee8398cf3d9b3c
--- /dev/null
+++ b/xplan-gateway/Dockerfile
@@ -0,0 +1,41 @@
+ARG XPLANBOX_VERSION=latest
+ARG XPLANBOX_IMAGE_NAME_PREFIX=xplanbox
+
+FROM ${XPLANBOX_IMAGE_NAME_PREFIX}/xplan-docker-tomcat:$XPLANBOX_VERSION as builder
+
+FROM eclipse-temurin:17.0.11_9-jre-alpine
+ARG BUILD_DATE=?
+ARG DOCKER_IMAGE_NAME=?
+ARG GIT_REVISION=?
+ARG WAR_FILE=target/*-repackaged.war
+ARG XPLANBOX_VERSION=latest
+
+# see https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys
+LABEL "org.opencontainers.image.created"="$BUILD_DATE" \
+	"org.opencontainers.image.description"="ozgxplanung xPlanBox component" \
+	"org.opencontainers.image.licenses"="GNU Affero General Public License & others" \
+	"org.opencontainers.image.ref.name"="$DOCKER_IMAGE_NAME" \
+	"org.opencontainers.image.revision"="$GIT_REVISION" \
+	"org.opencontainers.image.title"="ozgxplanung - $DOCKER_IMAGE_NAME" \
+	"org.opencontainers.image.url"="https://gitlab.opencode.de/diplanung/ozgxplanung" \
+	"org.opencontainers.image.vendor"="lat/lon GmbH" \
+	"org.opencontainers.image.version"="$XPLANBOX_VERSION"
+
+ENV TZ=Europe/Berlin
+
+# copy jmx exporter from xplan-docker-tomcat until we switch to actuator based prometheus publishing
+ENV JMX_EXPORTER_DIR=/xplanbox/prometheus
+RUN mkdir -p $JMX_EXPORTER_DIR
+COPY --from=builder $JMX_EXPORTER_DIR $JMX_EXPORTER_DIR
+
+ENV JAVA_ADDITIONAL_ARG_JMX_EXPORTER='-javaagent:$JMX_EXPORTER_DIR/jmx_prometheus_javaagent-1.0.1.jar=12345:$JMX_EXPORTER_DIR/jmx-exporter.config.yaml'
+
+# set environment variables
+ENV JAVA_ADDITIONAL_ARG_APP="-Duser.timezone=Europe/Berlin"
+
+COPY ${WAR_FILE} /xplanbox/app.war
+COPY run.sh /xplanbox/
+
+USER 1001
+
+ENTRYPOINT ["/bin/sh", "/xplanbox/run.sh"]
diff --git a/xplan-gateway/README.md b/xplan-gateway/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..065d6da8c08a4fd079b1ea3cc49b67182961c8de
--- /dev/null
+++ b/xplan-gateway/README.md
@@ -0,0 +1,20 @@
+# xPlanGateway
+
+
+
+## Entwicklung
+
+Die Anwendung kann wie folgt lokal gestartet werden:
+
+```
+mvn spring-boot:run -Dspring-boot.run.profiles=dev
+```
+
+## Konfiguration
+
+Folgende Umgebungsvariable können für die Konfiguration der Anwendung verwendet werden:
+
+- `LOG4J_LAYOUT`: das Logging Format `plain` oder `json` (Default: `plain`)
+- `XPLAN_MAPSERVER_URL_INTERNAL`: die interne root Url von `xplan-mapserver` (Default: `http://xplan-mapserver:8080`)
+- `XPLAN_MAPPROXY_URL_INTERNAL`: die interne root Url von `xplan-mapproxy` (Default: `http://xplan-mapproxy:8080`)
+- `XPLAN_SERVICES_URL_INTERNAL`: die internre root Url von `xplan-services` (Default: `http://xplan-services`)
diff --git a/xplan-gateway/pom.xml b/xplan-gateway/pom.xml
new file mode 100755
index 0000000000000000000000000000000000000000..f95ab92c503a951777292943af8d61d07ec30d6d
--- /dev/null
+++ b/xplan-gateway/pom.xml
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<artifactId>xplan-gateway</artifactId>
+	<packaging>war</packaging>
+
+	<parent>
+		<groupId>de.latlon.product.xplanbox</groupId>
+		<artifactId>xplanbox</artifactId>
+		<version>8.0-SNAPSHOT</version>
+	</parent>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+				<configuration>
+					<classifier>repackaged</classifier>
+				</configuration>
+				<executions>
+					<execution>
+						<goals>
+							<goal>repackage</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+			<plugin><!-- redeclare here to run *after* spring-boot repackage -->
+				<groupId>io.fabric8</groupId>
+				<artifactId>docker-maven-plugin</artifactId>
+				<executions>
+					<execution>
+						<id>context-sources</id>
+						<goals>
+							<goal>source</goal>
+						</goals>
+						<configuration>
+							<skip>${docker-image.skip-sources}</skip>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-jar-plugin</artifactId>
+				<configuration>
+					<archive>
+						<manifest>
+							<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+						</manifest>
+					</archive>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-war-plugin</artifactId>
+				<configuration>
+					<failOnMissingWebXml>false</failOnMissingWebXml>
+					<archive>
+						<manifest>
+							<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+						</manifest>
+					</archive>
+					<webResources>
+						<resource>
+							<directory>src/main/webapp</directory>
+							<includes>
+								<include>**/version.txt</include>
+							</includes>
+							<filtering>true</filtering>
+						</resource>
+						<resource>
+							<directory>src/main/webapp</directory>
+							<excludes>
+								<exclude>**/version.txt</exclude>
+							</excludes>
+							<filtering>false</filtering>
+						</resource>
+					</webResources>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-gateway</artifactId>
+			<version>4.1.5</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-actuator</artifactId>
+			<exclusions>
+				<exclusion>
+					<groupId>org.springframework.boot</groupId>
+					<artifactId>spring-boot-starter-logging</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-log4j2</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.fasterxml.jackson.dataformat</groupId>
+			<artifactId>jackson-dataformat-yaml</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.logging.log4j</groupId>
+			<artifactId>log4j-layout-template-json</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-thymeleaf</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-test</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+
+  <profiles>
+    <profile>
+      <id>docker</id>
+      <properties>
+        <docker-image.skip>false</docker-image.skip>
+        <docker-contextTarFile.expectedSizeInMat10pct>38</docker-contextTarFile.expectedSizeInMat10pct>
+      </properties>
+      <dependencies>
+        <dependency> <!-- faked maven dependency to be after base docker image in the reactor build  -->
+          <groupId>de.latlon.product.xplanbox</groupId>
+          <artifactId>xplan-docker-tomcat</artifactId>
+          <version>${project.version}</version>
+          <type>pom</type>
+        </dependency>
+      </dependencies>
+    </profile>
+  </profiles>
+</project>
diff --git a/xplan-gateway/run.sh b/xplan-gateway/run.sh
new file mode 100755
index 0000000000000000000000000000000000000000..9da77a35839ad040f46d7781afa3084db7bb46af
--- /dev/null
+++ b/xplan-gateway/run.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+ALL_ADDITIONAL_ARGS=$(env | grep ^JAVA_ADDITIONAL_ | sed 's/^JAVA_ADDITIONAL_[[:alnum:]_]*=//' | tr '\n' ' ')
+
+if [ -n "${ALL_ADDITIONAL_ARGS}" ]; then
+    JAVA_OPTS=$(eval "echo $ALL_ADDITIONAL_ARGS")
+    echo "xPlanBox JAVA_OPTS set: $JAVA_OPTS"
+fi
+
+exec java $JAVA_OPTS -jar /xplanbox/app.war
diff --git a/xplan-gateway/src/main/java/de/latlon/xplanbox/gateway/Configuration.java b/xplan-gateway/src/main/java/de/latlon/xplanbox/gateway/Configuration.java
new file mode 100644
index 0000000000000000000000000000000000000000..1f881cd9a6015d2e7a18585f2470f4ae18b248c6
--- /dev/null
+++ b/xplan-gateway/src/main/java/de/latlon/xplanbox/gateway/Configuration.java
@@ -0,0 +1,243 @@
+/*-
+ * #%L
+ * xplan-core-validator-events - Modul zur Gruppierung der Kernmodule
+ * %%
+ * Copyright (C) 2008 - 2024 Freie und Hansestadt Hamburg, developed by lat/lon gesellschaft für raumbezogene Informationssysteme mbH
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * 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%
+ */
+package de.latlon.xplanbox.gateway;
+
+import java.net.URI;
+import java.util.function.Function;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.gateway.route.Route;
+import org.springframework.cloud.gateway.route.RouteLocator;
+import org.springframework.cloud.gateway.route.builder.Buildable;
+import org.springframework.cloud.gateway.route.builder.PredicateSpec;
+import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
+import org.springframework.context.annotation.Bean;
+
+/**
+ * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
+ * @since 8.0
+ */
+public class Configuration {
+
+	@Value("${xplanbox.gateway.rewrite.backend.xplan-mapserver.uri}")
+	private URI backendXplanMapserver;
+
+	@Value("${xplanbox.gateway.rewrite.backend.xplan-mapproxy.uri}")
+	private URI backendXplanMapproxy;
+
+	@Value("${xplanbox.gateway.rewrite.backend.xplan-services.uri}")
+	private URI backendXplanServices;
+
+	@Bean
+	public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
+		return builder.routes()
+			// xplan-services:
+			// /xplan-ows/syn?SERVICE=WMS -> /xplan-wms/services/wms
+			.route("/xplan-ows/syn?SERVICE=WMS -> /xplan-wms/services/wms",
+					pathWithWmsServiceToUri("/xplan-ows/syn", "/xplan-wms/services/wms"))
+			// /xplan-ows/syn-pre?SERVICE=WMS -> /xplan-wms/services/wmspre
+			.route("/xplan-ows/syn-pre?SERVICE=WMS -> /xplan-wms/services/wmspre",
+					pathWithWmsServiceToUri("/xplan-ows/syn-pre", "/xplan-wms/services/wmspre"))
+			// /xplan-ows/syn-archive?SERVICE=WMS-> /xplan-wms/services/wmsarchive
+			.route("/xplan-ows/syn-archive?SERVICE=WMS-> /xplan-wms/services/wmsarchive",
+					pathWithWmsServiceToUri("/xplan-ows/syn-archive", "/xplan-wms/services/wmsarchive"))
+			// /xplan-ows/syn/planart/bp?SERVICE=WMS -> /xplan-wms/services/bpwms (analog:
+			// fpwms, lpwms, rpwms, sowms)
+			.route("/xplan-ows/syn/planart/bp?SERVICE=WMS -> /xplan-wms/services/bpwms",
+					pathWithWmsServiceToUri("/xplan-ows/syn/planart/bp", "/xplan-wms/services/bpwms"))
+			.route("/xplan-ows/syn/planart/fp?SERVICE=WMS -> /xplan-wms/services/fpwms",
+					pathWithWmsServiceToUri("/xplan-ows/syn/planart/fp", "/xplan-wms/services/fpwms"))
+			.route("/xplan-ows/syn/planart/lp?SERVICE=WMS -> /xplan-wms/services/lpwms",
+					pathWithWmsServiceToUri("/xplan-ows/syn/planart/lp", "/xplan-wms/services/lpwms"))
+			.route("/xplan-ows/syn/planart/rp?SERVICE=WMS -> /xplan-wms/services/rpwms",
+					pathWithWmsServiceToUri("/xplan-ows/syn/planart/rp", "/xplan-wms/services/rpwms"))
+			.route("/xplan-ows/syn/planart/so?SERVICE=WMS -> /xplan-wms/services/sowms",
+					pathWithWmsServiceToUri("/xplan-ows/syn/planart/so", "/xplan-wms/services/sowms"))
+			// /xplan-ows/syn-pre/planart/bp?SERVICE=WMS -> /xplan-wms/services/bpwmspre
+			// (analog: fpwmspre, lpwmspre, rpwmspre, sowmspre)
+			.route("/xplan-ows/syn-pre/planart/bp?SERVICE=WMS -> /xplan-wms/services/bpwmspre",
+					pathWithWmsServiceToUri("/xplan-ows/syn-pre/planart/bp", "/xplan-wms/services/bpwmspre"))
+			.route("/xplan-ows/syn-pre/planart/fp?SERVICE=WMS -> /xplan-wms/services/fpwmspre",
+					pathWithWmsServiceToUri("/xplan-ows/syn-pre/planart/fp", "/xplan-wms/services/fpwmspre"))
+			.route("/xplan-ows/syn-pre/planart/lp?SERVICE=WMS -> /xplan-wms/services/lpwmspre",
+					pathWithWmsServiceToUri("/xplan-ows/syn-pre/planart/lp", "/xplan-wms/services/lpwmspre"))
+			.route("/xplan-ows/syn-pre/planart/rp?SERVICE=WMS -> /xplan-wms/services/rpwmspre",
+					pathWithWmsServiceToUri("/xplan-ows/syn-pre/planart/rp", "/xplan-wms/services/rpwmspre"))
+			.route("/xplan-ows/syn-pre/planart/so?SERVICE=WMS -> /xplan-wms/services/sowmspre",
+					pathWithWmsServiceToUri("/xplan-ows/syn-pre/planart/so", "/xplan-wms/services/sowmspre"))
+
+			// /xplan-ows/syn-archive/planart/bp?SERVICE=WMS ->
+			// /xplan-wms/services/bpwmsarchive (analog: fpwmsarchive, lpwmsarchive,
+			// rpwmsarchive, sowmsarchive)
+			.route("/xplan-ows/syn-archive/planart/bp?SERVICE=WMS -> /xplan-wms/services/bpwmsarchive",
+					pathWithWmsServiceToUri("/xplan-ows/syn-archive/planart/bp", "/xplan-wms/services/bpwmsarchive"))
+			.route("/xplan-ows/syn-archive/planart/fp?SERVICE=WMS -> /xplan-wms/services/fpwmsarchive",
+					pathWithWmsServiceToUri("/xplan-ows/syn-archive/planart/fp", "/xplan-wms/services/fpwmsarchive"))
+			.route("/xplan-ows/syn-archive/planart/lp?SERVICE=WMS -> /xplan-wms/services/lpwmsarchive",
+					pathWithWmsServiceToUri("/xplan-ows/syn-archive/planart/lp", "/xplan-wms/services/lpwmsarchive"))
+			.route("/xplan-ows/syn-archive/planart/rp?SERVICE=WMS -> /xplan-wms/services/rpwmsarchive",
+					pathWithWmsServiceToUri("/xplan-ows/syn-archive/planart/rp", "/xplan-wms/services/rpwmsarchive"))
+			.route("/xplan-ows/syn-archive/planart/so?SERVICE=WMS -> /xplan-wms/services/sowmsarchive",
+					pathWithWmsServiceToUri("/xplan-ows/syn-archive/planart/so", "/xplan-wms/services/sowmsarchive"))
+
+			// /xplan-ows/syn/planwerk/{planName}?SERVICE=WMS ->
+			// /xplan-wms/services/planwerkwms/planname/{planName}
+			.route("/xplan-ows/syn/planwerk/{planName}?SERVICE=WMS -> /xplan-wms/services/planwerkwms/planname/{planName}",
+					r -> r.path("/xplan-ows/syn/planwerk/*")
+						.and()
+						.query("SERVICE", "WMS")
+						.filters(f -> f.rewritePath("/xplan-ows/syn/planwerk/(?<planName>.*)",
+								"/xplan-wms/services/planwerkwms/planname/${planName}")) //
+						.uri(backendXplanServices))
+			// /xplan-ows/syn-pre/planwerk/{planName}?SERVICE=WMS ->
+			// /xplan-wms/services/planwerkwmspre/planname/{planName}
+			.route("/xplan-ows/syn-pre/planwerk/{planName}?SERVICE=WMS -> /xplan-wms/services/planwerkwmspre/planname/{planName}",
+					r -> r.path("/xplan-ows/syn-pre/planwerk/*")
+						.and()
+						.query("SERVICE", "WMS")
+						.filters(f -> f.rewritePath("/xplan-ows/syn-pre/planwerk/(?<planName>.*)",
+								"/xplan-wms/services/planwerkwmspre/planname/${planName}")) //
+						.uri(backendXplanServices))
+
+			// /xplan-ows/syn?SERVICE=WFS -> /xplansyn-wfs/services/xplansynwfs
+			.route("/xplan-ows/syn?SERVICE=WFS -> /xplansyn-wfs/services/xplansynwfs",
+					pathWithWfsServiceToUri("/xplan-ows/syn", "/xplansyn-wfs/services/xplansynwfs"))
+			.route("/xplan-ows/syn-pre?SERVICE=WFS -> /xplansyn-wfs/services/xplansynwfspre",
+					pathWithWfsServiceToUri("/xplan-ows/syn-pre", "/xplansyn-wfs/services/xplansynwfspre"))
+			// /xplan-ows/syn-archive?SERVICE=WFS ->
+			// /xplansyn-wfs/services/xplansynwfsarchive
+			.route("/xplan-ows/syn-archive?SERVICE=WFS -> /xplansyn-wfs/services/xplansynwfsarchive",
+					pathWithWfsServiceToUri("/xplan-ows/syn-archive", "/xplansyn-wfs/services/xplansynwfsarchive"))
+			// /xplan-ows/5.1?SERVICE=WFS etc. -> /xplan-wfs/services/wfs51 (analog:
+			// wfs40,wfs41,wfs50,wfs51,wfs52,wfs53,wfs54,wfs60)
+			.route("/xplan-ows/4.0?SERVICE=WFS -> /xplan-wfs/services/wfs40", pathWithWfsVersion("4.0"))
+			.route("/xplan-ows/4.1?SERVICE=WFS -> /xplan-wfs/services/wfs41", pathWithWfsVersion("4.1"))
+			.route("/xplan-ows/5.0?SERVICE=WFS -> /xplan-wfs/services/wfs50", pathWithWfsVersion("5.0"))
+			.route("/xplan-ows/5.1?SERVICE=WFS -> /xplan-wfs/services/wfs51", pathWithWfsVersion("5.1"))
+			.route("/xplan-ows/5.2?SERVICE=WFS -> /xplan-wfs/services/wfs52", pathWithWfsVersion("5.2"))
+			.route("/xplan-ows/5.3?SERVICE=WFS -> /xplan-wfs/services/wfs53", pathWithWfsVersion("5.3"))
+			.route("/xplan-ows/5.4?SERVICE=WFS -> /xplan-wfs/services/wfs54", pathWithWfsVersion("5.4"))
+			.route("/xplan-ows/6.0?SERVICE=WFS -> /xplan-wfs/services/wfs60", pathWithWfsVersion("6.0"))
+			// /xplan-ows/5.1-pre?SERVICE=WFS etc. -> /xplan-wfs/services/wfs51pre
+			// (analog:
+			// wfs40pre,wfs41pre,wfs50pre,wfs51pre,wfs52pre,wfs53pre,wfs54pre,wfs60pre)
+			.route("/xplan-ows/4.0-pre?SERVICE=WFS -> /xplan-wfs/services/wfs40pre", pathWithWfsVersionPre("4.0"))
+			.route("/xplan-ows/4.1-pre?SERVICE=WFS -> /xplan-wfs/services/wfs41pre", pathWithWfsVersionPre("4.1"))
+			.route("/xplan-ows/5.0-pre?SERVICE=WFS -> /xplan-wfs/services/wfs50pre", pathWithWfsVersionPre("5.0"))
+			.route("/xplan-ows/5.1-pre?SERVICE=WFS -> /xplan-wfs/services/wfs51pre", pathWithWfsVersionPre("5.1"))
+			.route("/xplan-ows/5.2-pre?SERVICE=WFS -> /xplan-wfs/services/wfs52pre", pathWithWfsVersionPre("5.2"))
+			.route("/xplan-ows/5.3-pre?SERVICE=WFS -> /xplan-wfs/services/wfs53pre", pathWithWfsVersionPre("5.3"))
+			.route("/xplan-ows/5.4-pre?SERVICE=WFS -> /xplan-wfs/services/wfs54pre", pathWithWfsVersionPre("5.4"))
+			.route("/xplan-ows/6.0-pre?SERVICE=WFS -> /xplan-wfs/services/wfs60pre", pathWithWfsVersionPre("6.0"))
+			// /xplan-ows/5.1-archive?SERVICE=WFS etc. -> /xplan-wfs/services/wfs51archive
+			// (analog:
+			// wfs40archive,wfs41archive,wfs50archive,wfs51archive,wfs52archive,wfs53archive,wfs54archive,wfs60archive)
+			.route("/xplan-ows/4.0-archive?SERVICE=WFS -> /xplan-wfs/services/wfs40archive",
+					pathWithWfsVersionArchive("4.0"))
+			.route("/xplan-ows/4.1-archive?SERVICE=WFS -> /xplan-wfs/services/wfs41archive",
+					pathWithWfsVersionArchive("4.1"))
+			.route("/xplan-ows/5.0-archive?SERVICE=WFS -> /xplan-wfs/services/wfs50archive",
+					pathWithWfsVersionArchive("5.0"))
+			.route("/xplan-ows/5.1-archive?SERVICE=WFS -> /xplan-wfs/services/wfs51archive",
+					pathWithWfsVersionArchive("5.1"))
+			.route("/xplan-ows/5.2-archive?SERVICE=WFS -> /xplan-wfs/services/wfs52archive",
+					pathWithWfsVersionArchive("5.2"))
+			.route("/xplan-ows/5.3-archive?SERVICE=WFS -> /xplan-wfs/services/wfs53archive",
+					pathWithWfsVersionArchive("5.3"))
+			.route("/xplan-ows/5.4-archive?SERVICE=WFS -> /xplan-wfs/services/wfs54archive",
+					pathWithWfsVersionArchive("5.4"))
+			.route("/xplan-ows/6.0-archive?SERVICE=WFS -> /xplan-wfs/services/wfs60archive",
+					pathWithWfsVersionArchive("6.0"))
+
+			// xplan-mapproxy:
+			// /xplan-ows/cache/tiles/* -> xplan-mapproxy /wmts/1.0.0/*
+			.route("/xplan-ows/cache/tiles/* -> xplan-mapproxy /wmts/1.0.0/*",
+					r -> r.path("/xplan-ows/cache/tiles/*")
+						.filters(
+								f -> f.rewritePath("/xplan-ows/cache/tiles/(?<fragment>.*)", "/wmts/1.0.0/${fragment}")) //
+						.uri(backendXplanMapproxy))
+
+			// /xplan-ows/cache -> xplan-mapproxy /ows
+			.route("/xplan-ows/cache -> xplan-mapproxy/ows", r -> r.path("/xplan-ows/cache") //
+				.filters(f -> f.rewritePath("/xplan-ows/cache", "/ows")) //
+				.uri(backendXplanMapproxy))
+
+			// xplan-mapserver:
+			// /xplan-ows/raster -> /mapserver
+			.route("/xplan-ows/raster -> /mapserver", r -> r.path("/xplan-ows/raster") //
+				.filters(f -> f.rewritePath("/xplan-ows/raster", "/")) //
+				.uri(backendXplanMapserver))
+
+			// /xplan-ows/raster-pre -> /mapserver
+			.route("/xplan-ows/raster-pre -> /mapserver", r -> r.path("/xplan-ows/raster-pre") //
+				.filters(f -> f.rewritePath("/xplan-ows/raster-pre", "/")) //
+				.uri(backendXplanMapserver))
+			// /xplan-ows/raster/planwerk/{planName} → /mapserver?planname={planName}
+			.route("/xplan-ows/raster/planwerk/{planName} →  /mapserver?planname={planName}", r -> r
+				.path("/xplan-ows/raster/planwerk/*")
+				.filters(f -> f.rewritePath("/xplan-ows/raster/planwerk/(?<planName>.*)", "/?planname=${planName}")) //
+				.uri(backendXplanMapserver))
+			// /xplan-ows/raster/planart/{planArt} → /mapserver?planart={planArt}
+			.route("/xplan-ows/raster/planart/{planArt} →  /mapserver?planart={planArt}",
+					r -> r.path("/xplan-ows/raster/planart/*")
+						.filters(f -> f.rewritePath("/xplan-ows/raster/planart/(?<planArt>.*)", "/?planart=${planArt}")) //
+						.uri(backendXplanMapserver))
+
+			.build();
+	}
+
+	private Function<PredicateSpec, Buildable<Route>> pathWithWfsVersionArchive(String version) {
+		String versionWithoutDot = version.replaceAll("\\.", "");
+
+		return pathWithWfsServiceToUri("/xplan-ows/" + version + "-archive",
+				"/xplan-wfs/services/wfs" + versionWithoutDot + "archive");
+	}
+
+	private Function<PredicateSpec, Buildable<Route>> pathWithWfsVersionPre(String version) {
+		String versionWithoutDot = version.replaceAll("\\.", "");
+
+		return pathWithWfsServiceToUri("/xplan-ows/" + version + "-pre",
+				"/xplan-wfs/services/wfs" + versionWithoutDot + "pre");
+	}
+
+	private Function<PredicateSpec, Buildable<Route>> pathWithWfsVersion(String version) {
+		String versionWithoutDot = version.replaceAll("\\.", "");
+
+		return pathWithWfsServiceToUri("/xplan-ows/" + version, "/xplan-wfs/services/wfs" + versionWithoutDot);
+	}
+
+	private Function<PredicateSpec, Buildable<Route>> pathWithWmsServiceToUri(String path, String newPath) {
+		return r -> r.path(path)
+			.and()
+			.query("SERVICE", "WMS") //
+			.filters(f -> f.rewritePath(path, newPath)) //
+			.uri(backendXplanServices);
+	}
+
+	private Function<PredicateSpec, Buildable<Route>> pathWithWfsServiceToUri(String path, String newPath) {
+		return r -> r.path(path)
+			.and()
+			.query("SERVICE", "WFS") //
+			.filters(f -> f.rewritePath(path, newPath)) //
+			.uri(backendXplanServices);
+	}
+
+}
diff --git a/xplan-gateway/src/main/java/de/latlon/xplanbox/gateway/XPlanGatewayApplication.java b/xplan-gateway/src/main/java/de/latlon/xplanbox/gateway/XPlanGatewayApplication.java
new file mode 100644
index 0000000000000000000000000000000000000000..14bb9fa78969f89c84f31cf886b68d9b7146891c
--- /dev/null
+++ b/xplan-gateway/src/main/java/de/latlon/xplanbox/gateway/XPlanGatewayApplication.java
@@ -0,0 +1,39 @@
+/*-
+ * #%L
+ * xplan-core-validator-events - Modul zur Gruppierung der Kernmodule
+ * %%
+ * Copyright (C) 2008 - 2024 Freie und Hansestadt Hamburg, developed by lat/lon gesellschaft für raumbezogene Informationssysteme mbH
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * 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%
+ */
+package de.latlon.xplanbox.gateway;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Import;
+
+/**
+ * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
+ * @since 8.0
+ */
+@SpringBootApplication
+@Import(Configuration.class)
+public class XPlanGatewayApplication {
+
+	public static void main(String[] args) {
+		SpringApplication.run(XPlanGatewayApplication.class, args);
+	}
+
+}
diff --git a/xplan-gateway/src/main/resources/application-dev.properties b/xplan-gateway/src/main/resources/application-dev.properties
new file mode 100644
index 0000000000000000000000000000000000000000..0cf17686eaaa0999302453372759dbfdf3a3e1a7
--- /dev/null
+++ b/xplan-gateway/src/main/resources/application-dev.properties
@@ -0,0 +1,24 @@
+###
+# #%L
+# xplan-gateway - Gateway Modul
+# %%
+# Copyright (C) 2008 - 2024 Freie und Hansestadt Hamburg, developed by lat/lon gesellschaft für raumbezogene Informationssysteme mbH
+# %%
+# This program is free software: you can redistribute it and/or modify
+# 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%
+###
+
+## for local development
+
+server.port=8095
\ No newline at end of file
diff --git a/xplan-gateway/src/main/resources/application.properties b/xplan-gateway/src/main/resources/application.properties
new file mode 100644
index 0000000000000000000000000000000000000000..8ea924ecf0b3c365d9c0fddfca100b54df26f302
--- /dev/null
+++ b/xplan-gateway/src/main/resources/application.properties
@@ -0,0 +1,28 @@
+###
+# #%L
+# xplan-gateway - Gateway Modul
+# %%
+# Copyright (C) 2008 - 2024 Freie und Hansestadt Hamburg, developed by lat/lon gesellschaft für raumbezogene Informationssysteme mbH
+# %%
+# This program is free software: you can redistribute it and/or modify
+# 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%
+###
+management.endpoint.health.probes.enabled=true
+
+spring.cloud.gateway.predicate.cloud-foundry-route-service.enabled=false
+spring.main.banner-mode=off
+
+xplanbox.gateway.rewrite.backend.xplan-mapserver.uri=${XPLAN_MAPSERVER_URL_INTERNAL:http://xplan-mapserver:8080}
+xplanbox.gateway.rewrite.backend.xplan-mapproxy.uri=${XPLAN_MAPPROXY_URL_INTERNAL:http://xplan-mapproxy:8080}
+xplanbox.gateway.rewrite.backend.xplan-services.uri=${XPLAN_SERVICES_URL_INTERNAL:http://xplan-services}
diff --git a/xplan-gateway/src/main/resources/log4j2.yaml b/xplan-gateway/src/main/resources/log4j2.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..901fd96b68f83974f0b57d61c3310ef1b64bac0d
--- /dev/null
+++ b/xplan-gateway/src/main/resources/log4j2.yaml
@@ -0,0 +1,50 @@
+###
+# #%L
+# xplan-dokumente-api - Software zur Verwaltung von XPlanGML Daten
+# %%
+# Copyright (C) 2008 - 2024 Freie und Hansestadt Hamburg, developed by lat/lon gesellschaft für raumbezogene Informationssysteme mbH
+# %%
+# This program is free software: you can redistribute it and/or modify
+# 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%
+###
+Configuration:
+  name: XPlanGateway
+  status: warn
+  Properties:
+    Property:
+      name: appenderToUse
+      value: stdout_${env:LOG4J_LAYOUT:-plain}
+  
+  Appenders:
+    Console:
+      - name: stdout_plain
+        target: SYSTEM_OUT
+        PatternLayout:
+          Pattern: "%d %p %C{1.} [%t] %m%n"
+      - name: stdout_json
+        target: SYSTEM_OUT
+        JsonTemplateLayout:
+          eventTemplateUri: classpath:minimalist-format.json
+
+  Loggers:
+    Root:
+      level: info
+      AppenderRef:
+        - ref: ${appenderToUse}
+          level: info
+    Logger:
+      - name: org.springframework
+        level: warn
+      - name: org.apache
+        level: warn
diff --git a/xplan-gateway/src/main/resources/minimalist-format.json b/xplan-gateway/src/main/resources/minimalist-format.json
new file mode 100644
index 0000000000000000000000000000000000000000..607b5c00bed20b49df3b5ada848324d3099674c8
--- /dev/null
+++ b/xplan-gateway/src/main/resources/minimalist-format.json
@@ -0,0 +1,46 @@
+{
+  "@timestamp": {
+    "$resolver": "timestamp"
+  },
+  "level": {
+    "$resolver": "level",
+    "field": "name"
+  },
+  "logger_name": {
+    "$resolver": "logger",
+    "field": "name"
+  },
+  "thread_name": {
+    "$resolver": "thread",
+    "field": "name"
+  },
+  "message": {
+    "$resolver": "message",
+    "stringified": true
+  },
+  "traceId": {
+  	"$resolver": "pattern",
+  	"pattern": "%X{traceId}"
+  },
+  "spanId": {
+  	"$resolver": "pattern",
+  	"pattern": "%X{spanId}"
+  },
+  "exception": {
+    "exception_class": {
+      "$resolver": "exception",
+      "field": "className"
+    },
+    "exception_message": {
+      "$resolver": "exception",
+      "field": "message"
+    },
+    "stacktrace": {
+      "$resolver": "exception",
+      "field": "stackTrace",
+      "stackTrace": {
+        "stringified": true
+      }
+    }
+  }
+}
diff --git a/xplan-gateway/src/main/resources/templates/error/404.html b/xplan-gateway/src/main/resources/templates/error/404.html
new file mode 100644
index 0000000000000000000000000000000000000000..340fb784d06fb04d67ae4e8983af4a8636cb6e17
--- /dev/null
+++ b/xplan-gateway/src/main/resources/templates/error/404.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+<body>
+<h1>xPlanBox Gateway</h1>
+
+No route defined for this request.
+</body>
+</html>
\ No newline at end of file
diff --git a/xplan-gateway/src/main/webapp/version.txt b/xplan-gateway/src/main/webapp/version.txt
new file mode 100644
index 0000000000000000000000000000000000000000..24775311d69b031224fe91db6b4bdd96bdebbf94
--- /dev/null
+++ b/xplan-gateway/src/main/webapp/version.txt
@@ -0,0 +1,2 @@
+git.commit.id=${git.commit.id}
+build.key=${build.key}
\ No newline at end of file
diff --git a/xplan-gateway/src/test/java/de/latlon/xplanbox/gateway/ConfigurationTest.java b/xplan-gateway/src/test/java/de/latlon/xplanbox/gateway/ConfigurationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..7eb613f086a9589ab805fd4bc9a5d843fef5b752
--- /dev/null
+++ b/xplan-gateway/src/test/java/de/latlon/xplanbox/gateway/ConfigurationTest.java
@@ -0,0 +1,326 @@
+package de.latlon.xplanbox.gateway;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.boot.test.web.server.LocalServerPort;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.DynamicPropertyRegistry;
+import org.springframework.test.context.DynamicPropertySource;
+import org.springframework.test.web.reactive.server.WebTestClient;
+
+import com.sun.net.httpserver.HttpServer;
+
+/**
+ * Inspired from https://www.baeldung.com/spring-cloud-gateway-url-rewriting
+ */
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
+@ActiveProfiles("test")
+class ConfigurationTest {
+
+	@LocalServerPort
+	private int localPort;
+
+	@Autowired
+	private WebTestClient webClient;
+
+	private static List<HttpServer> mockServers = new ArrayList<>();
+
+	private static Logger log = LoggerFactory.getLogger(ConfigurationTest.class);
+
+	// Create a running HttpServer that echoes back the request URL.
+	private static HttpServer startTestServer(String hostDescription) {
+
+		try {
+			log.info("Starting mock server {}", hostDescription);
+			HttpServer mockServer = HttpServer.create();
+			mockServer.bind(new InetSocketAddress(0), 0);
+			mockServer.createContext("/", (xchg) -> {
+				String uri = xchg.getRequestURI().toString();
+				log.info("{} backend called: uri={}", hostDescription, uri);
+				xchg.getResponseHeaders().add("Content-Type", "text/plain");
+				xchg.sendResponseHeaders(200, 0);
+				OutputStream os = xchg.getResponseBody();
+				String response = "[" + hostDescription + "]" + uri;
+				os.write(response.getBytes());
+				os.flush();
+				os.close();
+			});
+
+			mockServer.start();
+			mockServers.add(mockServer);
+			InetSocketAddress localAddr = mockServer.getAddress();
+			log.info("mock server {} started: local address={}", hostDescription, localAddr);
+
+			return mockServer;
+		}
+		catch (Exception ex) {
+			throw new RuntimeException(ex);
+		}
+
+	}
+
+	@DynamicPropertySource
+	static void registerBackendServer(DynamicPropertyRegistry registry) {
+
+		startAndRegister(registry, "xplan-mapserver");
+		startAndRegister(registry, "xplan-mapproxy");
+		startAndRegister(registry, "xplan-services");
+
+	}
+
+	private static void startAndRegister(DynamicPropertyRegistry registry, String serviceName) {
+		registry.add("xplanbox.gateway.rewrite.backend." + serviceName + ".uri", () -> {
+			HttpServer s = startTestServer(serviceName);
+			return "http://localhost:" + s.getAddress().getPort();
+		});
+	}
+
+	@AfterAll
+	public static void stopMockBackend() throws Exception {
+		log.info("Shutdown mock http servers");
+		mockServers.forEach((s) -> s.stop(1));
+	}
+
+	// /xplan-ows/syn?SERVICE=WMS -> [xplan-services]/xplan-wms/services/wms
+	@Test
+	void servicesSynWms() {
+		testForward("/xplan-ows/syn?SERVICE=WMS -> [xplan-services]/xplan-wms/services/wms?SERVICE=WMS");
+		testForward(
+				"/xplan-ows/syn?SERVICE=WMS&foo=123 -> [xplan-services]/xplan-wms/services/wms?SERVICE=WMS&foo=123");
+	}
+
+	// /xplan-ows/syn-pre?SERVICE=WMS -> [xplan-services]/xplan-wms/services/wmspre
+	@Test
+	void servicesSynWmsPreWms() {
+		testForward("/xplan-ows/syn-pre?SERVICE=WMS -> [xplan-services]/xplan-wms/services/wmspre?SERVICE=WMS");
+	}
+
+	// /xplan-ows/syn-archive?SERVICE=WMS-> [xplan-services]/xplan-wms/services/wmsarchive
+	@Test
+	void servicesSynWmsArchiveWms() {
+		testForward("/xplan-ows/syn-archive?SERVICE=WMS -> [xplan-services]/xplan-wms/services/wmsarchive?SERVICE=WMS");
+	}
+
+	// /xplan-ows/syn/planart/bp?SERVICE=WMS -> [xplan-services]/xplan-wms/services/bpwms
+	// (analog: fpwms, lpwms, rpwms, sowms)
+	@Test
+	void servicesSynWmsPlanart() {
+		testForward("/xplan-ows/syn/planart/bp?SERVICE=WMS -> [xplan-services]/xplan-wms/services/bpwms?SERVICE=WMS");
+		testForward("/xplan-ows/syn/planart/fp?SERVICE=WMS -> [xplan-services]/xplan-wms/services/fpwms?SERVICE=WMS");
+		testForward("/xplan-ows/syn/planart/lp?SERVICE=WMS -> [xplan-services]/xplan-wms/services/lpwms?SERVICE=WMS");
+		testForward("/xplan-ows/syn/planart/rp?SERVICE=WMS -> [xplan-services]/xplan-wms/services/rpwms?SERVICE=WMS");
+		testForward("/xplan-ows/syn/planart/so?SERVICE=WMS -> [xplan-services]/xplan-wms/services/sowms?SERVICE=WMS");
+	}
+
+	// /xplan-ows/syn-pre/planart/bp?SERVICE=WMS ->
+	// [xplan-services]/xplan-wms/services/bpwmspre (analog: fpwmspre, lpwmspre, rpwmspre,
+	// sowmspre)
+	@Test
+	void servicesSynPreWmsPlanart() {
+		testForward(
+				"/xplan-ows/syn-pre/planart/bp?SERVICE=WMS -> [xplan-services]/xplan-wms/services/bpwmspre?SERVICE=WMS");
+		testForward(
+				"/xplan-ows/syn-pre/planart/fp?SERVICE=WMS -> [xplan-services]/xplan-wms/services/fpwmspre?SERVICE=WMS");
+		testForward(
+				"/xplan-ows/syn-pre/planart/lp?SERVICE=WMS -> [xplan-services]/xplan-wms/services/lpwmspre?SERVICE=WMS");
+		testForward(
+				"/xplan-ows/syn-pre/planart/rp?SERVICE=WMS -> [xplan-services]/xplan-wms/services/rpwmspre?SERVICE=WMS");
+		testForward(
+				"/xplan-ows/syn-pre/planart/so?SERVICE=WMS -> [xplan-services]/xplan-wms/services/sowmspre?SERVICE=WMS");
+	}
+
+	// /xplan-ows/syn-archive/planart/bp?SERVICE=WMS ->
+	// [xplan-services]/xplan-wms/services/bpwmsarchive (analog: fpwmsarchive,
+	// lpwmsarchive, rpwmsarchive, sowmsarchive)
+	@Test
+	void servicesSynArchiveWmsPlanart() {
+		testForward(
+				"/xplan-ows/syn-archive/planart/bp?SERVICE=WMS -> [xplan-services]/xplan-wms/services/bpwmsarchive?SERVICE=WMS");
+		testForward(
+				"/xplan-ows/syn-archive/planart/fp?SERVICE=WMS -> [xplan-services]/xplan-wms/services/fpwmsarchive?SERVICE=WMS");
+		testForward(
+				"/xplan-ows/syn-archive/planart/lp?SERVICE=WMS -> [xplan-services]/xplan-wms/services/lpwmsarchive?SERVICE=WMS");
+		testForward(
+				"/xplan-ows/syn-archive/planart/rp?SERVICE=WMS -> [xplan-services]/xplan-wms/services/rpwmsarchive?SERVICE=WMS");
+		testForward(
+				"/xplan-ows/syn-archive/planart/so?SERVICE=WMS -> [xplan-services]/xplan-wms/services/sowmsarchive?SERVICE=WMS");
+	}
+
+	// /xplan-ows/syn/planwerk/{planName}?SERVICE=WMS ->
+	// [xplan-services]/xplan-wms/services/planwerkwms/planname/{planName}
+	@Test
+	void servicesSynWmsPlanwerk() {
+		testForward(
+				"/xplan-ows/syn/planwerk/foo?SERVICE=WMS -> [xplan-services]/xplan-wms/services/planwerkwms/planname/foo?SERVICE=WMS");
+	}
+
+	// /xplan-ows/syn-pre/planwerk/{planName}?SERVICE=WMS ->
+	// [xplan-services]/xplan-wms/services/planwerkwmspre/planname/{planName}
+	@Test
+	void servicesSynPreWmsPlanwerk() {
+		testForward(
+				"/xplan-ows/syn-pre/planwerk/foo?SERVICE=WMS -> [xplan-services]/xplan-wms/services/planwerkwmspre/planname/foo?SERVICE=WMS");
+	}
+
+	// /xplan-ows/syn?SERVICE=WFS -> [xplan-services]/xplansyn-wfs/services/xplansynwfs
+	@Test
+	void servicesSynWfs() {
+		testForward("/xplan-ows/syn?SERVICE=WFS -> [xplan-services]/xplansyn-wfs/services/xplansynwfs?SERVICE=WFS");
+	}
+
+	// /xplan-ows/syn-pre?SERVICE=WFS ->
+	// [xplan-services]/xplansyn-wfs/services/xplansynwfspre
+	@Test
+	void servicesSynPreWfs() {
+		testForward(
+				"/xplan-ows/syn-pre?SERVICE=WFS -> [xplan-services]/xplansyn-wfs/services/xplansynwfspre?SERVICE=WFS");
+	}
+
+	// /xplan-ows/syn-archive?SERVICE=WFS ->
+	// [xplan-services]/xplansyn-wfs/services/xplansynwfsarchive
+	@Test
+	void servicesSynArchiveWfs() {
+		testForward(
+				"/xplan-ows/syn-archive?SERVICE=WFS -> [xplan-services]/xplansyn-wfs/services/xplansynwfsarchive?SERVICE=WFS");
+	}
+
+	// /xplan-ows/5.1?SERVICE=WFS etc. -> [xplan-services]/xplan-wfs/services/wfs51
+	// (analog:
+	// wfs40,wfs41,wfs50,wfs51,wfs52,wfs53,wfs54,wfs60)
+	@Test
+	void servicesSynVersionWfs() {
+		testForward("/xplan-ows/4.0?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs40?SERVICE=WFS");
+		testForward("/xplan-ows/4.1?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs41?SERVICE=WFS");
+		testForward("/xplan-ows/5.0?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs50?SERVICE=WFS");
+		testForward("/xplan-ows/5.1?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs51?SERVICE=WFS");
+		testForward("/xplan-ows/5.2?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs52?SERVICE=WFS");
+		testForward("/xplan-ows/5.3?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs53?SERVICE=WFS");
+		testForward("/xplan-ows/5.4?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs54?SERVICE=WFS");
+		testForward("/xplan-ows/6.0?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs60?SERVICE=WFS");
+	}
+
+	// /xplan-ows/5.1-pre?SERVICE=WFS etc. -> [xplan-services]/xplan-wfs/services/wfs51pre
+	// (analog: wfs40pre,wfs41pre,wfs50pre,wfs51pre,wfs52pre,wfs53pre,wfs54pre,wfs60pre)
+	@Test
+	void servicesSynPreVersionWfs() {
+		testForward("/xplan-ows/4.0-pre?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs40pre?SERVICE=WFS");
+		testForward("/xplan-ows/4.1-pre?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs41pre?SERVICE=WFS");
+		testForward("/xplan-ows/5.0-pre?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs50pre?SERVICE=WFS");
+		testForward("/xplan-ows/5.1-pre?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs51pre?SERVICE=WFS");
+		testForward("/xplan-ows/5.2-pre?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs52pre?SERVICE=WFS");
+		testForward("/xplan-ows/5.3-pre?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs53pre?SERVICE=WFS");
+		testForward("/xplan-ows/5.4-pre?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs54pre?SERVICE=WFS");
+		testForward("/xplan-ows/6.0-pre?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs60pre?SERVICE=WFS");
+	}
+
+	// /xplan-ows/5.1-archive?SERVICE=WFS etc. ->
+	// [xplan-services]/xplan-wfs/services/wfs51archive (analog:
+	// wfs40archive,wfs41archive,wfs50archive,wfs51archive,wfs52archive,wfs53archive,wfs54archive,wfs60archive)
+	@Test
+	void servicesSynArchiveVersionWfs() {
+		testForward(
+				"/xplan-ows/4.0-archive?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs40archive?SERVICE=WFS");
+		testForward(
+				"/xplan-ows/4.1-archive?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs41archive?SERVICE=WFS");
+		testForward(
+				"/xplan-ows/5.0-archive?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs50archive?SERVICE=WFS");
+		testForward(
+				"/xplan-ows/5.1-archive?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs51archive?SERVICE=WFS");
+		testForward(
+				"/xplan-ows/5.2-archive?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs52archive?SERVICE=WFS");
+		testForward(
+				"/xplan-ows/5.3-archive?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs53archive?SERVICE=WFS");
+		testForward(
+				"/xplan-ows/5.4-archive?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs54archive?SERVICE=WFS");
+		testForward(
+				"/xplan-ows/6.0-archive?SERVICE=WFS -> [xplan-services]/xplan-wfs/services/wfs60archive?SERVICE=WFS");
+	}
+
+	// xplan-mapproxy:
+	// /xplan-ows/cache/tiles/* -> xplan-mapproxy /wmts/1.0.0/*
+	@Test
+	void mapProxyCacheTiles() {
+		testForward("/xplan-ows/cache/tiles/foo -> [xplan-mapproxy]/wmts/1.0.0/foo");
+		testForward("/xplan-ows/cache/tiles/foo?x=o -> [xplan-mapproxy]/wmts/1.0.0/foo?x=o");
+
+		// not matched
+		testNotFound("/xplan-ows/cache/tiles/foo1/foo2");
+	}
+
+	// /xplan-ows/cache -> xplan-mapproxy /ows
+	@Test
+	void mapProxyCache() {
+		testForward("/xplan-ows/cache -> [xplan-mapproxy]/ows");
+		testForward("/xplan-ows/cache?x=y -> [xplan-mapproxy]/ows?x=y");
+
+		// not matched
+		testNotFound("/xplan-ows/cache/foo");
+	}
+
+	// xplan-mapserver:
+	// /xplan-ows/raster -> /mapserver
+	@Test
+	void mapServerRaster() {
+		testForward("/xplan-ows/raster -> [xplan-mapserver]/");
+		testForward("/xplan-ows/raster?foo=456 -> [xplan-mapserver]/?foo=456");
+	}
+
+	// /xplan-ows/raster-pre -> /mapserver
+	@Test
+	void mapServerRasterPre() {
+		testForward("/xplan-ows/raster-pre -> [xplan-mapserver]/");
+	}
+
+	// /xplan-ows/raster/planwerk/{planName} → /mapserver?planname={planName}
+	@Test
+	void mapServerRasterPlanwerk() {
+		testForward("/xplan-ows/raster/planwerk/myPlan -> [xplan-mapserver]/?planname=myPlan");
+	}
+
+	// /xplan-ows/raster/planart/{planArt} → /mapserver?planart={planArt}
+	@Test
+	void mapServerRasterPlanart() {
+		testForward("/xplan-ows/raster/planart/myPlanArt ->  [xplan-mapserver]/?planart=myPlanArt");
+	}
+
+	/**
+	 * @param requestToTarget "/to/request -> /expected/target"
+	 */
+	private void testForward(String requestToTarget) {
+		String[] parts = requestToTarget.split("->");
+		testForward(parts[0].trim(), parts[1].trim());
+	}
+
+	private void testForward(String requested, String targetted) {
+		webClient.get()
+			.uri("http://localhost:" + localPort + requested)
+			.exchange()
+			.expectBody()
+			.consumeWith((result) -> {
+				String body = new String(result.getResponseBody());
+				log.info("body={}", body);
+				assertEquals(targetted, body);
+			});
+	}
+
+	private void testNotFound(String requested) {
+		webClient.get()
+			.uri("http://localhost:" + localPort + requested)
+			.exchange() //
+			.expectStatus()
+			.isNotFound();
+	}
+
+}
\ No newline at end of file
diff --git a/xplan-gateway/src/test/resources/application-test.properties b/xplan-gateway/src/test/resources/application-test.properties
new file mode 100644
index 0000000000000000000000000000000000000000..2f759cdf35bd21a2ca45d774090dff3b4407578f
--- /dev/null
+++ b/xplan-gateway/src/test/resources/application-test.properties
@@ -0,0 +1,23 @@
+###
+# #%L
+# xplan-gateway - Gateway Modul
+# %%
+# Copyright (C) 2008 - 2024 Freie und Hansestadt Hamburg, developed by lat/lon gesellschaft für raumbezogene Informationssysteme mbH
+# %%
+# This program is free software: you can redistribute it and/or modify
+# 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%
+###
+
+
+logging.level.root=error
diff --git a/xplan-manager/xplan-manager-api/.trivyignore b/xplan-manager/xplan-manager-api/.trivyignore
index 3bdef816df8ab974c21ae560fcee5f6da8099bc6..a89d1b4a1aa6b42ed031bd1a456b6d2db778e3d3 100644
--- a/xplan-manager/xplan-manager-api/.trivyignore
+++ b/xplan-manager/xplan-manager-api/.trivyignore
@@ -1 +1 @@
-CVE-2016-1000027
\ No newline at end of file
+# no issue to ignore currently
\ No newline at end of file
diff --git a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/PlanInfoBuilder.java b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/PlanInfoBuilder.java
index 6ad088e423be35a6268ceb85e68b2f88f537fbc6..0feacea6bc203c20da1fe624664c532d8c4da384 100644
--- a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/PlanInfoBuilder.java
+++ b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/PlanInfoBuilder.java
@@ -240,10 +240,10 @@ public class PlanInfoBuilder {
 			pathSegments.add(detectService());
 			pathSegments.add("planname");
 			pathSegments.add(xPlan.getName().replace("/", ""));
+			pathSegments.remove("");
 			uriBuilder.setPathSegments(pathSegments);
 			URI planwerkWmsRef = uriBuilder.build();
-			Link planwerkWmsLink = (Link) new Link().rel(PLANWERKWMS).href(planwerkWmsRef).title(xPlan.getName());
-			return planwerkWmsLink;
+			return (Link) new Link().rel(PLANWERKWMS).href(planwerkWmsRef).title(xPlan.getName());
 		}
 		catch (URISyntaxException e) {
 			LOG.warn("Could not build XPlanwerkWMS url: " + e.getMessage(), e);
diff --git a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/XPlanBoxContentTypes.java b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/XPlanContentTypes.java
similarity index 96%
rename from xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/XPlanBoxContentTypes.java
rename to xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/XPlanContentTypes.java
index a65c4817ea5eb40e94de93e3de4d3191b4f45e77..cac89286d0e70f9d0fb3116d7509de2936a127c1 100644
--- a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/XPlanBoxContentTypes.java
+++ b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/XPlanContentTypes.java
@@ -26,9 +26,9 @@ import jakarta.ws.rs.core.MediaType;
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
  * @since 5.0
  */
-public class XPlanBoxContentTypes {
+public class XPlanContentTypes {
 
-	private XPlanBoxContentTypes() {
+	private XPlanContentTypes() {
 	}
 
 	public static final String XPLANBOX_NO_VERSION_JSON = "application/vnd.xplanbox.api+json";
diff --git a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/config/ApplicationContext.java b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/config/ApplicationContext.java
index 05f1344674f5bb5658a3fc50e575c281e0a2e5cc..79499b25ddbdb614475ad1d723786a7886d62c2d 100644
--- a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/config/ApplicationContext.java
+++ b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/config/ApplicationContext.java
@@ -83,7 +83,7 @@ import de.latlon.xplanbox.api.commons.handler.SystemConfigHandler;
 import de.latlon.xplanbox.core.raster.config.RasterEvaluationContext;
 import de.latlon.xplanbox.core.raster.evaluation.XPlanRasterEvaluator;
 import de.latlon.xplanbox.security.config.SecurityContext;
-import de.latlon.xplanbox.validator.storage.config.AmazonS3Context;
+import de.latlon.xplanbox.validator.storage.config.AmazonS3ValidationContext;
 import org.deegree.cs.coordinatesystems.ICRS;
 import org.deegree.cs.exceptions.UnknownCRSException;
 import org.deegree.cs.persistence.CRSManager;
@@ -105,7 +105,7 @@ import org.springframework.core.io.ResourceLoader;
 @Configuration
 @ComponentScan(basePackages = { "de.latlon.xplanbox.api.manager.handler" })
 @Import({ SecurityContext.class, JpaContext.class, AmazonS3RasterStorageContext.class,
-		AmazonS3DocumentStorageContext.class, AmazonS3Context.class, RasterEvaluationContext.class })
+		AmazonS3DocumentStorageContext.class, AmazonS3ValidationContext.class, RasterEvaluationContext.class })
 public class ApplicationContext {
 
 	@Autowired
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 8694485a01596916df98047a7a235d3f9d0448be..5249787732d17fe27d0c2b08648c808c412e3e36 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,9 +20,7 @@
  */
 package de.latlon.xplanbox.api.manager.executor;
 
-import static de.latlon.core.validator.events.v1.XPlanboxPublicV1Event.EventType.IMPORT_FINISHED;
-import static de.latlon.core.validator.events.v1.XPlanboxPublicV1Event.EventType.IMPORT_STARTED;
-import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.APPLICATION_ZIP;
+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;
 import static de.latlon.xplanbox.validator.storage.exception.ErrorType.INVALID_REQUEST;
@@ -33,33 +31,21 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.util.Collections;
 import java.util.List;
-import java.util.stream.Collectors;
 
-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.planimport.ImportRequestedEvent;
-import de.latlon.core.validator.events.v1.XPlanboxPublicV1Event;
+import de.latlon.core.validator.events.v1.XPlanPublicV1Event;
 import de.latlon.xplan.commons.archive.XPlanArchive;
 import de.latlon.xplan.commons.archive.XPlanArchiveCreator;
 import de.latlon.xplan.commons.s3.StorageException;
 import de.latlon.xplan.manager.transaction.UnsupportPlanException;
-import de.latlon.xplan.manager.web.shared.XPlan;
-import de.latlon.xplanbox.api.commons.ObjectMapperContextResolver;
 import de.latlon.xplanbox.api.commons.exception.InvalidXPlanGmlOrArchive;
 import de.latlon.xplanbox.api.commons.exception.XPlanApiException;
-import de.latlon.xplanbox.api.manager.PlanInfoBuilder;
-import de.latlon.xplanbox.api.manager.config.ManagerApiConfiguration;
 import de.latlon.xplanbox.api.manager.handler.PlanHandler;
-import de.latlon.xplanbox.api.manager.v1.model.Bereich;
-import de.latlon.xplanbox.api.manager.v1.model.Gemeinde;
-import de.latlon.xplanbox.api.manager.v2.model.PlanInfo;
 import de.latlon.xplanbox.validator.storage.StatusType;
-import de.latlon.xplanbox.validator.storage.StoredImportedPlans;
 import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
-import jakarta.ws.rs.core.MediaType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -83,28 +69,35 @@ public class PlanImporter {
 	@Autowired
 	private ValidationExecutionStorage validationExecutionStorage;
 
-	@Autowired
-	private ManagerApiConfiguration managerApiConfiguration;
-
-	private XPlanArchiveCreator archiveCreator = new XPlanArchiveCreator();
+	private final XPlanArchiveCreator archiveCreator = new XPlanArchiveCreator();
 
 	public void importPlan(ImportRequestedEvent event) throws Exception {
+		if (event.getValidationResult() != ImportRequestedEvent.VALIDATION_RESULT.VALID) {
+			validationExecutionStorage.changeStatus(event.getUuid(), StatusType.IMPORT_ABORTED,
+					"Import aborted due to invalid XPlanGML");
+			return;
+		}
+		if (event
+			.getExternalReferencesResult() != ImportRequestedEvent.EXTERNAL_REFERENCES_RESULT.AVAILABLE_AND_VALID) {
+			validationExecutionStorage.changeStatus(event.getUuid(), StatusType.IMPORT_ABORTED,
+					"Import aborted due missing external References or invalid Rasterfiles");
+			return;
+		}
+		doImportPlan(event);
+	}
+
+	private void doImportPlan(ImportRequestedEvent event) throws Exception {
 		validationExecutionStorage.changeStatus(event.getUuid(), StatusType.IMPORT_STARTED);
-		eventSender.sendPublicEvent(new XPlanboxPublicV1Event(IMPORT_STARTED, event.getUuid(), "import started"));
+		eventSender.sendPublicEvent(new XPlanPublicV1Event(IMPORT_STARTED, event.getUuid(), "import started"));
 		Path tmpPath = Files.createTempFile(event.getUuid(), ".rcv");
 		if (Files.exists(tmpPath))
 			Files.delete(tmpPath);
 		try {
 			XPlanArchive archive = createArchive(event, tmpPath);
-			List<XPlan> xPlans = planHandler.importPlanWithoutValidation(archive, event.getInternalId(),
+			List<Integer> planIds = planHandler.importPlanWithoutValidation(archive, event.getInternalId(),
 					event.getPlanStatus());
-			List<PlanInfo> planInfo = createPlanInfo(xPlans, event.isSupportsGetPlanByIdAsZip());
-			Path pathToPlanInfo = createPlanInfoFile(planInfo);
-			List<String> planIds = xPlans.stream().map(xPlan -> xPlan.getId()).toList();
-			StoredImportedPlans storedImportedPlans = validationExecutionStorage.savePlanInfo(event.getUuid(),
-					pathToPlanInfo, planIds);
-			LOG.info("Imported plans: {}", planInfo.size());
-			validationExecutionStorage.changeStatus(event.getUuid(), StatusType.IMPORT_FINISHED, storedImportedPlans);
+			LOG.info("Imported plans: {}", planIds.size());
+			validationExecutionStorage.changeStatus(event.getUuid(), StatusType.IMPORT_FINISHED, planIds);
 			validationExecutionStorage.cleanupAfterValidation(event.getUuid());
 		}
 		catch (XPlanApiException e) {
@@ -125,17 +118,11 @@ public class PlanImporter {
 		}
 		finally {
 			Files.delete(tmpPath);
-			eventSender.sendPublicEvent(new XPlanboxPublicV1Event(IMPORT_FINISHED, event.getUuid(), "import finished"));
+			eventSender.sendPublicEvent(new XPlanPublicV1Event(XPlanPublicV1Event.EventType.IMPORT_FINISHED,
+					event.getUuid(), "import finished"));
 		}
 	}
 
-	private Path createPlanInfoFile(List<PlanInfo> planInfos) throws IOException {
-		ObjectMapper mapper = new ObjectMapperContextResolver().getContext(List.class);
-		Path planInfoFile = Files.createTempFile("", ".json");
-		mapper.writeValue(planInfoFile.toFile(), planInfos);
-		return planInfoFile;
-	}
-
 	private XPlanArchive createArchive(ImportRequestedEvent event, Path tmpPath)
 			throws IOException, StorageException, InvalidXPlanGmlOrArchive {
 		validationExecutionStorage.writePlanToValidate(event.getUuid(), tmpPath);
@@ -165,22 +152,4 @@ public class PlanImporter {
 		}
 	}
 
-	private List<PlanInfo> createPlanInfo(List<XPlan> plans, boolean supportsGetPlanByIdAsZip) {
-		return plans.stream().map(plan -> {
-			List<String> alternateMediaTypes = alternateMediaTypes(supportsGetPlanByIdAsZip);
-			List<Bereich> bereiche = planHandler.findBereiche(plan.getId());
-			List<Gemeinde> gemeinden = planHandler.findGemeinden(plan.getId());
-			return new PlanInfoBuilder(plan, bereiche, gemeinden, managerApiConfiguration)
-				.selfMediaType(MediaType.APPLICATION_JSON_TYPE.toString())
-				.alternateMediaType(alternateMediaTypes)
-				.buildV2();
-		}).collect(Collectors.toList());
-	}
-
-	private List<String> alternateMediaTypes(boolean supportsGetPlanByIdAsZip) {
-		if (supportsGetPlanByIdAsZip)
-			return Collections.singletonList(APPLICATION_ZIP);
-		return Collections.emptyList();
-	}
-
 }
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 5939b2a48392ac0171e0b8a6d4ffb424543ba7d6..cf3835c0940d08d2f5e653df4b4271ad79a95b69 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
@@ -79,15 +79,13 @@ public class PlanHandler {
 	@Autowired
 	private XPlanExporter xPlanExporter;
 
-	public List<XPlan> importPlanWithoutValidation(XPlanArchive xPlanArchive, String internalId, String planStatus)
+	public List<Integer> importPlanWithoutValidation(XPlanArchive xPlanArchive, String internalId, String planStatus)
 			throws Exception {
 		LOG.info("Importing plan into storage for '{}'", StringUtils.normalizeSpace(planStatus));
 		PlanStatus targetPlanStatus = determineTargetPlanStatus(xPlanArchive, planStatus);
 		List<Integer> planIds = xPlanInsertManager.importPlan(xPlanArchive, false, true, internalId, targetPlanStatus);
-		List<XPlan> plansById = findPlansById(planIds);
-		LOG.info("Plan successfully imported. Ids: {}",
-				plansById.stream().map(plan -> plan.getId()).collect(Collectors.joining(",")));
-		return plansById;
+		LOG.info("Plan successfully imported. Ids: {}", planIds);
+		return planIds;
 	}
 
 	public StatusMessage deletePlan(String planId) throws Exception {
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 32fd40c45d9c7ec94f20b37888906ec3a21e2c4d..5a739c385297b885eacf4d0bb8278c5bc67ccef5 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
@@ -55,9 +55,8 @@ public class Receiver {
 		LOG.info("Received event: " + event);
 
 		try {
-			if (event.getValidationResult() == ImportRequestedEvent.VALIDATION_RESULT.VALID && event
-				.getExternalReferencesResult() == ImportRequestedEvent.EXTERNAL_REFERENCES_RESULT.AVAILABLE_AND_VALID)
-				planImporter.importPlan(event);
+
+			planImporter.importPlan(event);
 
 			ImportFinishedEvent finishedEvent = new ImportFinishedEvent(event.getUuid(), IMPORT_SUCCEEDED);
 			eventSender.sendEvent(finishedEvent);
diff --git a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v1/PlanApi.java b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v1/PlanApi.java
index e3a8889724aba6d459242cbbbc499e2a954c1d22..340bdce5032199916aec9cf9a88f0d5c50e88af7 100644
--- a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v1/PlanApi.java
+++ b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v1/PlanApi.java
@@ -27,16 +27,19 @@ import static de.latlon.xplan.commons.util.TextPatternConstants.INTERNALID_PATTE
 import static de.latlon.xplan.commons.util.TextPatternConstants.SIMPLE_NAME_PATTERN;
 import static de.latlon.xplanbox.api.commons.ValidatorConverter.createValidationSettings;
 import static de.latlon.xplanbox.api.commons.ValidatorConverter.detectOrCreateValidationName;
-import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.APPLICATION_ZIP;
-import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.APPLICATION_ZIP_TYPE;
-import static de.latlon.xplanbox.api.manager.XPlanBoxContentTypes.XPLANBOX_NO_VERSION_JSON;
-import static de.latlon.xplanbox.api.manager.XPlanBoxContentTypes.XPLANBOX_NO_VERSION_JSON_TYPE;
-import static de.latlon.xplanbox.api.manager.XPlanBoxContentTypes.XPLANBOX_V1_JSON;
-import static de.latlon.xplanbox.api.manager.XPlanBoxContentTypes.XPLANBOX_V1_JSON_TYPE;
-import static de.latlon.xplanbox.api.manager.XPlanBoxContentTypes.XPLANBOX_V2_JSON;
-import static de.latlon.xplanbox.api.manager.XPlanBoxContentTypes.XPLANBOX_V2_JSON_TYPE;
+import static de.latlon.xplanbox.api.commons.XPlanMediaType.APPLICATION_ZIP;
+import static de.latlon.xplanbox.api.commons.XPlanMediaType.APPLICATION_ZIP_TYPE;
+import static de.latlon.xplanbox.api.manager.XPlanContentTypes.XPLANBOX_NO_VERSION_JSON;
+import static de.latlon.xplanbox.api.manager.XPlanContentTypes.XPLANBOX_NO_VERSION_JSON_TYPE;
+import static de.latlon.xplanbox.api.manager.XPlanContentTypes.XPLANBOX_V1_JSON;
+import static de.latlon.xplanbox.api.manager.XPlanContentTypes.XPLANBOX_V1_JSON_TYPE;
+import static de.latlon.xplanbox.api.manager.XPlanContentTypes.XPLANBOX_V2_JSON;
+import static de.latlon.xplanbox.api.manager.XPlanContentTypes.XPLANBOX_V2_JSON_TYPE;
 import static de.latlon.xplanbox.api.manager.v1.model.Link.RelEnum.SELF;
+import static de.latlon.xplanbox.validator.storage.StatusType.IMPORT_ABORTED;
+import static de.latlon.xplanbox.validator.storage.StatusType.IMPORT_FAILED;
 import static de.latlon.xplanbox.validator.storage.StatusType.IMPORT_REQUESTED;
+import static de.latlon.xplanbox.validator.storage.StatusType.VALIDATION_FAILED;
 import static de.latlon.xplanbox.validator.storage.ValidationExecutionStorage.ReportType.JSON;
 import static io.swagger.v3.oas.annotations.enums.Explode.FALSE;
 import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
@@ -69,6 +72,7 @@ import de.latlon.xplanbox.api.commons.ValidationReportBuilder;
 import de.latlon.xplanbox.api.commons.exception.UnsupportedParameterValue;
 import de.latlon.xplanbox.api.commons.v1.model.ExternalReferenceResult;
 import de.latlon.xplanbox.api.commons.v1.model.ExternalReferenceStatusEnum;
+import de.latlon.xplanbox.api.commons.v1.model.RasterEvaluationResult;
 import de.latlon.xplanbox.api.commons.v2.model.CrsStatusEnum;
 import de.latlon.xplanbox.api.commons.v2.model.ImageFormatStatusEnum;
 import de.latlon.xplanbox.api.commons.v2.model.ValidationReport;
@@ -78,8 +82,9 @@ import de.latlon.xplanbox.api.manager.config.ManagerApiConfiguration;
 import de.latlon.xplanbox.api.manager.exception.InvalidApiVersion;
 import de.latlon.xplanbox.api.manager.exception.InvalidPlan;
 import de.latlon.xplanbox.api.manager.exception.InvalidPlanReferences;
-import de.latlon.xplanbox.api.manager.handler.AbstractAsyncImportWrapper;
 import de.latlon.xplanbox.api.manager.exception.InvalidRasterdata;
+import de.latlon.xplanbox.api.manager.exception.UnexpectedError;
+import de.latlon.xplanbox.api.manager.handler.AbstractAsyncImportWrapper;
 import de.latlon.xplanbox.api.manager.handler.PlanHandler;
 import de.latlon.xplanbox.api.manager.openapi.v1.ApiV1Config;
 import de.latlon.xplanbox.api.manager.v1.model.Bereich;
@@ -87,7 +92,9 @@ import de.latlon.xplanbox.api.manager.v1.model.Gemeinde;
 import de.latlon.xplanbox.api.manager.v1.model.Link;
 import de.latlon.xplanbox.api.manager.v1.model.PlanInfo;
 import de.latlon.xplanbox.api.manager.v1.model.StatusMessage;
+import de.latlon.xplanbox.validator.storage.Status;
 import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
+import de.latlon.xplanbox.validator.storage.exception.EventExecutionException;
 import io.swagger.v3.oas.annotations.Hidden;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
@@ -322,7 +329,6 @@ public class PlanApi {
 					@ApiResponse(responseCode = "200", description = "OK",
 							content = { @Content(mediaType = "application/json",
 									array = @ArraySchema(schema = @Schema(implementation = PlanInfo.class))) }),
-					@ApiResponse(responseCode = "404", description = "Invalid planName, plan not found"),
 					@ApiResponse(responseCode = "406", description = "Requested format is not available") })
 	public Response getByName(@Context Request request,
 			@PathParam("planName") @Parameter(description = "name of the plan to be returned",
@@ -362,9 +368,10 @@ public class PlanApi {
 				internalId, planStatus, ValidationRequestedEvent.MediaType.JSON, originFile, true);
 		importWrapper.sendEvent(event);
 
-		byte[] planInfosAsBytes = validationExecutionStorage.retrievePlanInfo(event.getUuid());
-		// validation failed
-		if (planInfosAsBytes == null) {
+		Status status = validationExecutionStorage.retrieveStatus(event.getUuid());
+		if (status.getStatusType() == IMPORT_FAILED || status.getStatusType() == VALIDATION_FAILED)
+			throw new EventExecutionException(status.getErrorMsg(), status.getErrorType());
+		if (status.getStatusType() == IMPORT_ABORTED) {
 			byte[] report = validationExecutionStorage.retrieveReport(uuid, JSON);
 			ValidationReport validationReport = createReportFileFrom(report);
 			if (!validationReport.getValid()) {
@@ -379,30 +386,35 @@ public class PlanApi {
 			if (!missingExternalReferences.isEmpty()) {
 				throw new InvalidPlanReferences(missingExternalReferences);
 			}
-			List<String> invalidRasterdata = validationReport.getExternalReferencesResult()
+			List<String> invalidRasterdata = validationReport.getRasterEvaluationResults()
 				.stream()
-				.filter(externalReferenceResult -> externalReferenceResult.getCrsStatus() == CrsStatusEnum.UNSUPPORTED
-						|| externalReferenceResult.getImageFormatStatus() == ImageFormatStatusEnum.UNSUPPORTED)
-				.map(ExternalReferenceResult::getName)
+				.filter(rasterEvaluationResult -> rasterEvaluationResult.getCrsStatus() == CrsStatusEnum.UNSUPPORTED
+						|| rasterEvaluationResult.getImageFormatStatus() == ImageFormatStatusEnum.UNSUPPORTED)
+				.map(RasterEvaluationResult::getName)
 				.toList();
 			if (!invalidRasterdata.isEmpty()) {
 				throw new InvalidRasterdata(invalidRasterdata);
 			}
+			throw new UnexpectedError(status.getErrorMsg());
 		}
-
-		List<PlanInfo> planInfos = createPlanInfoFileFrom(planInfosAsBytes);
-		MediaType originalRequestedMediaType = requestedMediaType(request);
-		if (XPLANBOX_V2_JSON_TYPE.equals(originalRequestedMediaType)) {
+		List<XPlan> xPlans = planHandler.findPlansById(status.getImportedPlanIds());
+		MediaType requestedMediaType = requestedMediaType(request);
+		if (XPLANBOX_V2_JSON_TYPE.equals(requestedMediaType)) {
+			List<PlanInfo> planInfos = createPlanInfo(requestedMediaType, xPlans);
 			return Response.created(getSelfLink(planInfos)).entity(planInfos).build();
 		}
-		if (planInfos.size() > 1) {
+		if (xPlans.size() > 1) {
 			throw new InvalidApiVersion("The imported XPlanArchive contains multiple XPlanGML instances, accept header "
 					+ XPLANBOX_V2_JSON + "  must be used to import this plan.");
 		}
-		PlanInfo planInfo = planInfos.get(0);
+		PlanInfo planInfo = createPlanInfo(requestedMediaType, xPlans.get(0));
 		return Response.created(getSelfLink(planInfo)).entity(planInfo).build();
 	}
 
+	private List<PlanInfo> createPlanInfo(MediaType requestedMediaType, List<XPlan> plans) {
+		return plans.stream().map(plan -> createPlanInfo(requestedMediaType, plan)).collect(Collectors.toList());
+	}
+
 	private PlanInfo createPlanInfo(MediaType requestedMediaType, XPlan planById) {
 		List<String> alternateMediaTypes = alternateMediaTypes(requestedMediaType);
 		List<Bereich> bereiche = planHandler.findBereiche(planById.getId());
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 78b98cd16abfc5728fd6bcaf9c176277a2222c17..9f6600bff0f00116c66294b535a8c50e2ba183a3 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
@@ -25,8 +25,8 @@ import static de.latlon.xplan.commons.util.TextPatternConstants.INTERNALID_PATTE
 import static de.latlon.xplan.commons.util.TextPatternConstants.SIMPLE_NAME_PATTERN;
 import static de.latlon.xplanbox.api.commons.ValidatorConverter.createValidationSettings;
 import static de.latlon.xplanbox.api.commons.ValidatorConverter.detectOrCreateValidationName;
-import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.APPLICATION_ZIP;
-import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.APPLICATION_ZIP_TYPE;
+import static de.latlon.xplanbox.api.commons.XPlanMediaType.APPLICATION_ZIP;
+import static de.latlon.xplanbox.api.commons.XPlanMediaType.APPLICATION_ZIP_TYPE;
 import static de.latlon.xplanbox.api.commons.v2.model.ResponseLink.RelEnum.STATUS;
 import static de.latlon.xplanbox.validator.storage.StatusType.IMPORT_REQUESTED;
 import static io.swagger.v3.oas.annotations.enums.Explode.FALSE;
@@ -115,7 +115,7 @@ public class PlanApi2 {
 	@Operation(operationId = "import", summary = "Import a XPlanGML or XPlanArchive",
 			description = "Imports a XPlanGML or XPlanArchive", tags = { "manage", },
 			responses = {
-					@ApiResponse(responseCode = "200", description = "successful operation",
+					@ApiResponse(responseCode = "200", description = "ImportReceipt with uuid of the import",
 							content = { @Content(mediaType = "application/json",
 									schema = @Schema(implementation = ImportReceipt.class)) }),
 					@ApiResponse(responseCode = "400", description = "Invalid input",
diff --git a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v2/StatusApi.java b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v2/StatusApi.java
index d83efc41e6e5b81d6c01c1b6a916fbe3dbe82651..daebb94561c5b9bb90f30a589a386f26dea9e252 100644
--- a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v2/StatusApi.java
+++ b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v2/StatusApi.java
@@ -30,8 +30,11 @@ import java.net.URISyntaxException;
 import de.latlon.xplan.commons.s3.StorageException;
 import de.latlon.xplanbox.api.commons.exception.InvalidValidationUuid;
 import de.latlon.xplanbox.api.commons.v2.model.ResponseLink;
-import de.latlon.xplanbox.api.commons.v2.model.StatusEnum;
-import de.latlon.xplanbox.api.commons.v2.model.StatusNotification;
+import de.latlon.xplanbox.api.commons.v2.model.ValidationReport;
+import de.latlon.xplanbox.api.manager.config.ManagerApiConfiguration;
+import de.latlon.xplanbox.api.manager.v2.model.ManagerStatusNotification;
+import de.latlon.xplanbox.api.manager.v2.model.PlanInfo;
+import de.latlon.xplanbox.api.manager.v2.model.StatusEnum;
 import de.latlon.xplanbox.validator.storage.Status;
 import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
 import io.swagger.v3.oas.annotations.Operation;
@@ -53,6 +56,9 @@ import org.springframework.beans.factory.annotation.Autowired;
 @Path("/status")
 public class StatusApi {
 
+	@Autowired
+	private ManagerApiConfiguration managerApiConfiguration;
+
 	@Autowired
 	private ValidationExecutionStorage validationExecutionStorage;
 
@@ -63,7 +69,7 @@ public class StatusApi {
 			responses = {
 					@ApiResponse(responseCode = "200", description = "StatusNotification",
 							content = { @Content(mediaType = APPLICATION_JSON,
-									schema = @Schema(implementation = StatusNotification.class)) }),
+									schema = @Schema(implementation = ManagerStatusNotification.class)) }),
 					@ApiResponse(responseCode = "404",
 							description = "Invalid uuid, no validation with the passed uuid found"),
 					@ApiResponse(responseCode = "406", description = "Requested format is not available") })
@@ -83,30 +89,47 @@ public class StatusApi {
 		}
 	}
 
-	public StatusNotification fromStatus(Status status) throws URISyntaxException {
-		StatusNotification statusNotification = new StatusNotification()
+	public ManagerStatusNotification fromStatus(Status status) throws URISyntaxException {
+		ManagerStatusNotification statusNotification = (ManagerStatusNotification) new ManagerStatusNotification()
 			.status(StatusEnum.valueOf(status.getStatusType().name()))
 			.importedPlanIds(status.getImportedPlanIds())
 			.errorMsg(status.getErrorMsg());
 		if (status.getLinkToJsonReport() != null)
-			statusNotification.links((ResponseLink) new ResponseLink().rel(REPORT)
+			statusNotification.addLink((ResponseLink) new ResponseLink().rel(REPORT)
+				.schema(createLinkToSchema(ValidationReport.class))
 				.expirationTime(status.getExpirationTime())
 				.type("application/json")
 				.title("Validierungsreport")
 				.href(new URI(status.getLinkToJsonReport())));
 		if (status.getLinkToPdfReport() != null)
-			statusNotification.links((ResponseLink) new ResponseLink().rel(REPORT)
+			statusNotification.addLink((ResponseLink) new ResponseLink().rel(REPORT)
 				.expirationTime(status.getExpirationTime())
 				.type("application/pdf")
 				.title("Validierungsreport")
 				.href(new URI(status.getLinkToPdfReport())));
-		if (status.getLinkToPlansMetadata() != null)
-			statusNotification.links((ResponseLink) new ResponseLink().rel(PLANINFO)
-				.expirationTime(status.getExpirationTime())
-				.type("application/json")
-				.title("PlanInfo")
-				.href(new URI(status.getLinkToPlansMetadata())));
+		if (status.getImportedPlanIds() != null)
+			status.getImportedPlanIds().forEach(planId -> {
+				statusNotification.addLink((ResponseLink) new ResponseLink().rel(PLANINFO)
+					.schema(createLinkToSchema(PlanInfo.class))
+					.type("application/json")
+					.title("PlanInfo " + planId)
+					.href(createLinkToStatus(planId)));
+			});
 		return statusNotification;
 	}
 
+	private URI createLinkToStatus(int planId) {
+		URI apiUrl = managerApiConfiguration.getApiUrl();
+		if (apiUrl == null)
+			return null;
+		return apiUrl.resolve("api/v2/plan/" + planId);
+	}
+
+	private URI createLinkToSchema(Class<?> schemaClass) {
+		URI apiUrl = managerApiConfiguration.getApiUrl();
+		if (apiUrl == null)
+			return null;
+		return apiUrl.resolve("api/v2#/components/schemas/" + schemaClass.getSimpleName());
+	}
+
 }
diff --git a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v2/model/ManagerStatusNotification.java b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v2/model/ManagerStatusNotification.java
new file mode 100644
index 0000000000000000000000000000000000000000..b3ebd329f91704bde4d8ed5de643b4242777a8a1
--- /dev/null
+++ b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v2/model/ManagerStatusNotification.java
@@ -0,0 +1,53 @@
+package de.latlon.xplanbox.api.manager.v2.model;
+
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY;
+
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+public class ManagerStatusNotification extends de.latlon.xplanbox.api.commons.v2.model.StatusNotification {
+
+	private StatusEnum status;
+
+	@JsonInclude(NON_EMPTY)
+	private List<Integer> importedPlanIds;
+
+	public ManagerStatusNotification() {
+	}
+
+	public ManagerStatusNotification(StatusEnum status) {
+		this.status = status;
+	}
+
+	public StatusEnum getStatus() {
+		return status;
+	}
+
+	public void setStatus(StatusEnum status) {
+		this.status = status;
+	}
+
+	public ManagerStatusNotification status(StatusEnum status) {
+		this.status = status;
+		return this;
+	}
+
+	public List<Integer> getImportedPlanIds() {
+		return importedPlanIds;
+	}
+
+	public void setImportedPlanIds(List<Integer> importedPlanIds) {
+		this.importedPlanIds = importedPlanIds;
+	}
+
+	public ManagerStatusNotification importedPlanIds(List<Integer> importedPlanIds) {
+		this.importedPlanIds = importedPlanIds;
+		return this;
+	}
+
+}
diff --git a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v2/model/StatusEnum.java b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v2/model/StatusEnum.java
similarity index 74%
rename from xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v2/model/StatusEnum.java
rename to xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v2/model/StatusEnum.java
index d89b03007de8b1ead8977fa374295cbfc9dd7e37..e7b5a0652575362136edccd505b3d8c5fab8999f 100644
--- a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v2/model/StatusEnum.java
+++ b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v2/model/StatusEnum.java
@@ -1,4 +1,4 @@
-package de.latlon.xplanbox.api.commons.v2.model;
+package de.latlon.xplanbox.api.manager.v2.model;
 
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
@@ -6,8 +6,8 @@ package de.latlon.xplanbox.api.commons.v2.model;
  */
 public enum StatusEnum {
 
-	// Validation requested
-	VALIDATION_REQUESTED,
+	// Import requested
+	IMPORT_REQUESTED,
 
 	// Validation started
 	VALIDATION_STARTED,
@@ -18,12 +18,12 @@ public enum StatusEnum {
 	// Validation finished
 	VALIDATION_FINISHED,
 
-	// Import requested
-	IMPORT_REQUESTED,
-
 	// Import started
 	IMPORT_STARTED,
 
+	// Import aborted due to incomplete XPlanArchive or invalid XPlanGML
+	IMPORT_ABORTED,
+
 	// Import failed
 	IMPORT_FAILED,
 
diff --git a/xplan-manager/xplan-manager-api/src/main/resources/application.properties b/xplan-manager/xplan-manager-api/src/main/resources/application.properties
index 7494502308a53ba783cc5c47dcf4a8c97cb37e80..9944a07c37ba0b1818a31a79519e594d92c9bbcd 100644
--- a/xplan-manager/xplan-manager-api/src/main/resources/application.properties
+++ b/xplan-manager/xplan-manager-api/src/main/resources/application.properties
@@ -20,8 +20,6 @@
 ###
 server.servlet.context-path=/xplan-manager-api
 
-spring.main.allow-bean-definition-overriding=true
-
 logging.level.root=warn
 logging.level.de.latlon=debug
 logging.level.org.springframework.web=debug
diff --git a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/ManagerApiJerseyTest.java b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/ManagerApiJerseyTest.java
index bdd8b2b25c7aa0113dadd0b8ecf607b1aa434690..3cf506dd798f626dd97836c4adbfe7d396fbf6dd 100644
--- a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/ManagerApiJerseyTest.java
+++ b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/ManagerApiJerseyTest.java
@@ -2,7 +2,6 @@ package de.latlon.xplanbox.api.manager;
 
 import java.lang.reflect.ParameterizedType;
 
-import de.latlon.xplan.core.manager.db.config.JpaContext;
 import de.latlon.xplanbox.api.commons.exception.XPlanApiExceptionMapper;
 import de.latlon.xplanbox.api.manager.config.ApplicationContext;
 import de.latlon.xplanbox.api.manager.config.HsqlJpaContext;
@@ -32,7 +31,7 @@ public abstract class ManagerApiJerseyTest<T> extends JerseyTest {
 		PropertySourcesPlaceholderConfigurer pph = new PropertySourcesPlaceholderConfigurer();
 		pph.setLocations(new ClassPathResource("/application.properties"), new ClassPathResource("/s3Mock.properties"));
 		context.addBeanFactoryPostProcessor(pph);
-		context.register(ApplicationContext.class, JpaContext.class, HsqlJpaContext.class, TestContext.class);
+		context.register(ApplicationContext.class, HsqlJpaContext.class, TestContext.class);
 		context.refresh();
 		resourceConfig.register(XPlanApiExceptionMapper.class);
 		resourceConfig.register(MultiPartFeature.class);
diff --git a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/PlanInfoBuilderTest.java b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/PlanInfoBuilderTest.java
index 2b76521b5c7049c90fdae3896739e707e1ee9ce8..8306025145715c82c15015cce8926b8c15a1fdb5 100644
--- a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/PlanInfoBuilderTest.java
+++ b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/PlanInfoBuilderTest.java
@@ -9,11 +9,13 @@ import java.net.URISyntaxException;
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
+import java.util.Optional;
 
 import de.latlon.xplan.manager.web.shared.XPlan;
 import de.latlon.xplanbox.api.manager.config.ManagerApiConfiguration;
 import de.latlon.xplanbox.api.manager.v1.model.Bereich;
 import de.latlon.xplanbox.api.manager.v1.model.Gemeinde;
+import de.latlon.xplanbox.api.manager.v1.model.Link;
 import de.latlon.xplanbox.api.manager.v1.model.PlanInfo;
 import de.latlon.xplanbox.api.manager.v1.model.PlanInfoXplanModelData;
 import org.junit.jupiter.api.Test;
@@ -51,6 +53,13 @@ public class PlanInfoBuilderTest {
 			.buildV2();
 		assertThat(planInfo.getId()).isEqualTo(1);
 		assertThat(planInfo.getType()).isEqualTo("BP_Plan");
+		Optional<Link> planwerkWms = planInfo.getLinks()
+			.stream()
+			.filter(l -> Link.RelEnum.PLANWERKWMS.equals(l.getRel()))
+			.findFirst();
+		assertThat(planwerkWms.isPresent()).isTrue();
+		assertThat(planwerkWms.get().getHref().toString())
+			.isEqualTo("http://example.org/xplan-services-wms/services/planwerkwms/planname/plan");
 
 		de.latlon.xplanbox.api.manager.v2.model.PlanInfoXplanModelData xplanModelData = planInfo.getXplanModelData();
 		assertThat(xplanModelData.getBereich().get(0).getName()).isEqualTo("testbereich");
@@ -90,6 +99,7 @@ public class PlanInfoBuilderTest {
 	private static ManagerApiConfiguration createManagerApiConfiguration() throws URISyntaxException {
 		ManagerApiConfiguration managerApiConfiguration = mock(ManagerApiConfiguration.class);
 		when(managerApiConfiguration.getApiUrl()).thenReturn(new URI("http://example.org/xplan-manager-api"));
+		when(managerApiConfiguration.getWmsUrl()).thenReturn(new URI("http://example.org/xplan-services-wms/"));
 		return managerApiConfiguration;
 	}
 
diff --git a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/config/FakeAsyncImportWrapper.java b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/config/FakeAsyncImportWrapper.java
index aa43bfbdf1e401f7d88fa1b2dc801d34c87ac390..4e6ae38d8ddb06c46b08f6a4b54cfa95a65a581b 100644
--- a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/config/FakeAsyncImportWrapper.java
+++ b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/config/FakeAsyncImportWrapper.java
@@ -1,5 +1,7 @@
 package de.latlon.xplanbox.api.manager.config;
 
+import static de.latlon.xplanbox.validator.storage.StatusType.IMPORT_FINISHED;
+
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Collections;
@@ -31,9 +33,7 @@ public class FakeAsyncImportWrapper extends AbstractAsyncImportWrapper {
 			Path reportForNextValidateRequest = Paths.get(getClass().getResource("validation-report.json").toURI());
 			reports.put(ValidationExecutionStorage.ReportType.JSON, reportForNextValidateRequest);
 			validationExecutionStorage.saveValidationResult(event.getUuid(), reports);
-
-			Path planInfo = Paths.get(getClass().getResource("planinfo.json").toURI());
-			validationExecutionStorage.savePlanInfo(event.getUuid(), planInfo, Collections.singletonList("1"));
+			validationExecutionStorage.changeStatus(event.getUuid(), IMPORT_FINISHED, Collections.singletonList(1));
 		}
 		catch (Exception e) {
 			throw new RuntimeException(e);
diff --git a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/config/HsqlJpaContext.java b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/config/HsqlJpaContext.java
index 6d2e5dd9aee879a4e490b516782d9dfb89942200..ebec8299962ab5dc6bc86374a54d8dd5b7343aba 100644
--- a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/config/HsqlJpaContext.java
+++ b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/config/HsqlJpaContext.java
@@ -20,15 +20,15 @@
  */
 package de.latlon.xplanbox.api.manager.config;
 
+import javax.sql.DataSource;
+import java.sql.SQLException;
+
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
 import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
 import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
 
-import javax.sql.DataSource;
-import java.sql.SQLException;
-
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
  * @since 7.0
@@ -46,7 +46,7 @@ public class HsqlJpaContext {
 	}
 
 	@Bean
-	public HibernateJpaVendorAdapter getJpaVendorAdapter() {
+	public HibernateJpaVendorAdapter jpaVendorAdapter() {
 		HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
 		vendorAdapter.setGenerateDdl(true);
 		vendorAdapter.setShowSql(true);
diff --git a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/config/TestContext.java b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/config/TestContext.java
index 49214e8861b63e1669c92f60aaeaa119268bf067..ed45b38835c2a6681bb28b4657a1569ce788c212 100644
--- a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/config/TestContext.java
+++ b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/config/TestContext.java
@@ -46,7 +46,6 @@ import java.sql.Statement;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.Optional;
 
 import de.latlon.core.validator.events.EventSender;
 import de.latlon.xplan.commons.XPlanSchemas;
@@ -72,8 +71,6 @@ import de.latlon.xplan.manager.wmsconfig.raster.storage.RasterStorage;
 import de.latlon.xplan.manager.workspace.WorkspaceException;
 import de.latlon.xplan.manager.workspace.WorkspaceReloader;
 import de.latlon.xplanbox.core.raster.evaluation.XPlanRasterEvaluator;
-import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
-import de.latlon.xplanbox.validator.storage.filesystem.FileSystemValidationExecutionStorage;
 import jakarta.annotation.PostConstruct;
 import jakarta.servlet.ServletContext;
 import org.deegree.cs.coordinatesystems.ICRS;
@@ -184,7 +181,7 @@ public class TestContext {
 	@Primary
 	public ManagerApiConfiguration managerApiConfiguration() throws URISyntaxException {
 		ManagerApiConfiguration managerApiConfiguration = mock(ManagerApiConfiguration.class);
-		when(managerApiConfiguration.getApiUrl()).thenReturn(new URI("http://localhost:8080/xplan-api-manager"));
+		when(managerApiConfiguration.getApiUrl()).thenReturn(new URI("http://localhost:8080/xplan-api-manager/"));
 		when(managerApiConfiguration.getDefaultValidationConfiguration())
 			.thenReturn(new DefaultValidationConfiguration());
 		return managerApiConfiguration;
@@ -317,11 +314,6 @@ public class TestContext {
 		return workspaceReloader;
 	}
 
-	@Bean
-	public ValidationExecutionStorage validationExecutionStorage() throws IOException {
-		return new FileSystemValidationExecutionStorage(Optional.empty());
-	}
-
 	@PostConstruct
 	void initLoggingAdapter() {
 		SLF4JBridgeHandler.removeHandlersForRootLogger();
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 40e4d6ca062b2e83f9ee15914e1ea02a21923551..570a6a6f438dab489c4e4820d9f926f077927140 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
@@ -2,60 +2,58 @@ package de.latlon.xplanbox.api.manager.executor;
 
 import static de.latlon.core.validator.events.planimport.ImportRequestedEvent.EXTERNAL_REFERENCES_RESULT.AVAILABLE_AND_VALID;
 import static de.latlon.core.validator.events.planimport.ImportRequestedEvent.VALIDATION_RESULT.VALID;
-import static de.latlon.core.validator.events.v1.XPlanboxPublicV1Event.EventType.IMPORT_FINISHED;
-import static de.latlon.core.validator.events.v1.XPlanboxPublicV1Event.EventType.IMPORT_STARTED;
+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_REQUESTED;
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyList;
 import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
-import static org.xmlunit.assertj.XmlAssert.assertThat;
 
-import java.io.IOException;
 import java.net.URI;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
 
 import de.latlon.core.validator.events.EventSender;
 import de.latlon.core.validator.events.ValidationRequestedEvent;
 import de.latlon.core.validator.events.planimport.ImportRequestedEvent;
-import de.latlon.core.validator.events.v1.XPlanboxPublicV1Event;
+import de.latlon.core.validator.events.v1.XPlanPublicV1Event;
 import de.latlon.xplan.commons.archive.XPlanArchive;
-import de.latlon.xplan.manager.web.shared.XPlan;
+import de.latlon.xplanbox.api.manager.config.ApplicationContext;
+import de.latlon.xplanbox.api.manager.config.HsqlJpaContext;
 import de.latlon.xplanbox.api.manager.config.ManagerApiConfiguration;
+import de.latlon.xplanbox.api.manager.config.TestContext;
 import de.latlon.xplanbox.api.manager.handler.PlanHandler;
-import de.latlon.xplanbox.validator.storage.StatusType;
-import de.latlon.xplanbox.validator.storage.StoredImportedPlans;
 import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
-import de.latlon.xplanbox.validator.storage.filesystem.FileSystemValidationExecutionStorage;
-import org.assertj.core.api.Assertions;
 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;
 import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Bean;
+import org.springframework.boot.test.mock.mockito.SpyBean;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.xmlunit.assertj.XmlAssert;
 
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
  * @since 8.0
  */
-@SpringBootTest(classes = { PlanImporter.class, PlanImporterTest.TestConfig.class })
+@SpringBootTest(classes = { PlanImporter.class })
+@ContextConfiguration(classes = { ApplicationContext.class, HsqlJpaContext.class, TestContext.class })
+@TestPropertySource(value = "/s3Mock.properties", properties = "spring.main.allow-bean-definition-overriding=true")
+@ActiveProfiles("test")
 public class PlanImporterTest {
 
 	@Autowired
 	private PlanImporter planImporter;
 
-	@Autowired
+	@SpyBean
 	private ValidationExecutionStorage validationExecutionStorage;
 
 	@MockBean
@@ -68,7 +66,7 @@ public class PlanImporterTest {
 	EventSender eventSender;
 
 	@Captor
-	ArgumentCaptor<XPlanboxPublicV1Event> publicEventCaptor;
+	ArgumentCaptor<XPlanPublicV1Event> publicEventCaptor;
 
 	@Captor
 	ArgumentCaptor<String> internalIdCaptor;
@@ -79,25 +77,11 @@ public class PlanImporterTest {
 	@Captor
 	ArgumentCaptor<Path> planInfoPathCaptor;
 
-	@TestConfiguration
-	static class TestConfig {
-
-		@Bean
-		public ValidationExecutionStorage validationExecutionStorage() throws IOException {
-			Optional<Path> fsExecutionDir = Optional.empty();
-			FileSystemValidationExecutionStorage fileSystemValidationExecutionStorage = new FileSystemValidationExecutionStorage(
-					fsExecutionDir);
-
-			return Mockito.spy(fileSystemValidationExecutionStorage);
-		}
-
-	}
-
 	@Test
 	void verifyImportPlan() throws Exception {
 		when(planHandler.importPlanWithoutValidation(any(XPlanArchive.class), anyString(), anyString()))
-			.thenReturn(createPlans());
-		when(managerApiConfiguration.getApiUrl()).thenReturn(new URI("http/localhost/manager/api/v2"));
+			.thenReturn(Collections.singletonList(1));
+		when(managerApiConfiguration.getApiUrl()).thenReturn(new URI("http/localhost/manager/api/v2/"));
 
 		Path pathToPlan = Paths.get(getClass().getResource("/xplan.gml").toURI());
 		String uuid = validationExecutionStorage.addPlanToValidate(pathToPlan, IMPORT_REQUESTED);
@@ -108,26 +92,15 @@ public class PlanImporterTest {
 
 		verify(planHandler).importPlanWithoutValidation(any(XPlanArchive.class), internalIdCaptor.capture(),
 				planStatusCaptor.capture());
-		assertThat(internalIdCaptor.getValue()).isEqualTo(event.getInternalId());
-		assertThat(planStatusCaptor.getValue()).isEqualTo(event.getPlanStatus());
+		XmlAssert.assertThat(internalIdCaptor.getValue()).isEqualTo(event.getInternalId());
+		XmlAssert.assertThat(planStatusCaptor.getValue()).isEqualTo(event.getPlanStatus());
 
-		verify(validationExecutionStorage).savePlanInfo(eq(uuid), planInfoPathCaptor.capture(), anyList());
-		verify(validationExecutionStorage).changeStatus(eq(uuid), eq(StatusType.IMPORT_FINISHED),
-				any(StoredImportedPlans.class));
 		verify(validationExecutionStorage).cleanupAfterValidation(uuid);
 
-		XPlanboxPublicV1Event expectedStartEvent = new XPlanboxPublicV1Event(IMPORT_STARTED, uuid, "import started");
-		XPlanboxPublicV1Event expectedFinishedEvent = new XPlanboxPublicV1Event(IMPORT_FINISHED, uuid,
-				"import finished");
-		Mockito.verify(eventSender, times(2)).sendPublicEvent(publicEventCaptor.capture());
-		Assertions.assertThat(publicEventCaptor.getAllValues())
-			.containsExactly(expectedStartEvent, expectedFinishedEvent);
-	}
-
-	private static List<XPlan> createPlans() {
-		XPlan plan = new XPlan("test", "1", "BP_Plan");
-		plan.setVersion("XPLAN_60");
-		return Collections.singletonList(plan);
+		XPlanPublicV1Event expectedStartEvent = new XPlanPublicV1Event(IMPORT_STARTED, uuid, "import started");
+		XPlanPublicV1Event expectedFinishedEvent = new XPlanPublicV1Event(IMPORT_FINISHED, uuid, "import finished");
+		verify(eventSender, times(2)).sendPublicEvent(publicEventCaptor.capture());
+		assertThat(publicEventCaptor.getAllValues()).containsExactly(expectedStartEvent, expectedFinishedEvent);
 	}
 
 }
diff --git a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/handler/EditBasisdatenHandlerTest.java b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/handler/EditBasisdatenHandlerTest.java
index baf885b574de2381eecc824bb68838fd52b5fed5..980b9ade04a3c659a30b4193f5b8c9f04cd47b7e 100644
--- a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/handler/EditBasisdatenHandlerTest.java
+++ b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/handler/EditBasisdatenHandlerTest.java
@@ -31,6 +31,7 @@ import de.latlon.xplanbox.api.manager.exception.InvalidPlanToEdit;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.TestPropertySource;
 
@@ -39,8 +40,8 @@ import org.springframework.test.context.TestPropertySource;
  */
 @SpringBootTest
 @ContextConfiguration(classes = { ApplicationContext.class, HsqlJpaContext.class, TestContext.class })
-@TestPropertySource(properties = { "xplanbox.s3.bucketName=test-bucket",
-		"xplanbox.validation.s3.bucketName=test-bucket-validation", "xplanbox.services.crs=EPSG:25832" })
+@TestPropertySource(value = "/s3Mock.properties", properties = "spring.main.allow-bean-definition-overriding=true")
+@ActiveProfiles("test")
 class EditBasisdatenHandlerTest {
 
 	@Autowired
diff --git a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/handler/PlanHandlerTest.java b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/handler/PlanHandlerTest.java
index e1cfd2dd430badd2a21321e67f023e94d5a8dd14..4e1cdf71ee8191214b7688d72e026766782a6098 100644
--- a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/handler/PlanHandlerTest.java
+++ b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/handler/PlanHandlerTest.java
@@ -37,6 +37,7 @@ import jakarta.ws.rs.core.StreamingOutput;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.TestPropertySource;
 
@@ -45,8 +46,8 @@ import org.springframework.test.context.TestPropertySource;
  */
 @SpringBootTest
 @ContextConfiguration(classes = { ApplicationContext.class, HsqlJpaContext.class, TestContext.class })
-@TestPropertySource(properties = { "xplanbox.s3.bucketName=test-bucket",
-		"xplanbox.validation.s3.bucketName=test-bucket-validation", "xplanbox.services.crs=EPSG:25832" })
+@TestPropertySource(value = "/s3Mock.properties", properties = "spring.main.allow-bean-definition-overriding=true")
+@ActiveProfiles("test")
 class PlanHandlerTest {
 
 	@Autowired
diff --git a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/v1/PlanApiTest.java b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/v1/PlanApiTest.java
index d11e050a76c05901a0b2a9bd10c866e5b99fe824..c2ca4e0e6793e7632e35a49f853ccd64360020b5 100644
--- a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/v1/PlanApiTest.java
+++ b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/v1/PlanApiTest.java
@@ -21,10 +21,10 @@
 package de.latlon.xplanbox.api.manager.v1;
 
 import static de.latlon.xplan.commons.XPlanVersion.XPLAN_41;
-import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.APPLICATION_X_ZIP;
-import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.APPLICATION_X_ZIP_COMPRESSED;
-import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.APPLICATION_ZIP;
-import static de.latlon.xplanbox.api.manager.XPlanBoxContentTypes.XPLANBOX_V2_JSON;
+import static de.latlon.xplanbox.api.commons.XPlanMediaType.APPLICATION_X_ZIP;
+import static de.latlon.xplanbox.api.commons.XPlanMediaType.APPLICATION_X_ZIP_COMPRESSED;
+import static de.latlon.xplanbox.api.commons.XPlanMediaType.APPLICATION_ZIP;
+import static de.latlon.xplanbox.api.manager.XPlanContentTypes.XPLANBOX_V2_JSON;
 import static de.latlon.xplanbox.api.manager.v1.model.PlanStatusEnum.FESTGESTELLT;
 import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
 import static jakarta.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
diff --git a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/v2/PlanApi2Test.java b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/v2/PlanApi2Test.java
index 6e7bf9d29df021ac07e3034bf92329b863e297ef..fd1c9c28e83d527a5cf213b3c9c76d98fa8bbcb0 100644
--- a/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/v2/PlanApi2Test.java
+++ b/xplan-manager/xplan-manager-api/src/test/java/de/latlon/xplanbox/api/manager/v2/PlanApi2Test.java
@@ -21,9 +21,9 @@
 package de.latlon.xplanbox.api.manager.v2;
 
 import static de.latlon.xplan.commons.XPlanVersion.XPLAN_41;
-import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.APPLICATION_X_ZIP;
-import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.APPLICATION_X_ZIP_COMPRESSED;
-import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.APPLICATION_ZIP;
+import static de.latlon.xplanbox.api.commons.XPlanMediaType.APPLICATION_X_ZIP;
+import static de.latlon.xplanbox.api.commons.XPlanMediaType.APPLICATION_X_ZIP_COMPRESSED;
+import static de.latlon.xplanbox.api.commons.XPlanMediaType.APPLICATION_ZIP;
 import static de.latlon.xplanbox.api.manager.v1.model.PlanStatusEnum.FESTGESTELLT;
 import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
 import static jakarta.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
diff --git a/xplan-manager/xplan-manager-api/src/test/resources/de/latlon/xplanbox/api/manager/config/planinfo.json b/xplan-manager/xplan-manager-api/src/test/resources/de/latlon/xplanbox/api/manager/config/planinfo.json
deleted file mode 100644
index 36e8c3c116ec2cf9422b0946f472a64ff81b3c9b..0000000000000000000000000000000000000000
--- a/xplan-manager/xplan-manager-api/src/test/resources/de/latlon/xplanbox/api/manager/config/planinfo.json
+++ /dev/null
@@ -1 +0,0 @@
-[{"id":3,"type":"BP_Plan","version":"XPLAN_54","planStatus":"FESTGESTELLT","raster":false,"importDate":"2024-08-07T12:43:01.873+0200","inspirePublished":false,"bbox":{"minX":9.982202,"minY":53.608754,"maxX":9.983553,"maxY":53.609485,"crs":"EPSG:4326"},"xplanModelData":{"name":"BPlan001_5-4","nummer":"-","internalId":null,"gemeinden": [{"ags":"02000000","gemeindeName":"Muster"}],"rechtsstand":"Satzung","inkrafttretensDatum":null,"bereiche":[{"nummer":"1","name":null}]},"links":[{"href":"http://localhost:8086/xmanager/api/v1/plan/3","type":"application/json","hreflang":null,"title":"BPlan001_5-4","length":null,"rel":"self"},{"href":"http://localhost:8086/xmanager/api/v1/plan/3","type":"application/xml","hreflang":null,"title":"BPlan001_5-4","length":null,"rel":"alternate"},{"href":"http://localhost:8086/xmanager/api/v1/plan/3","type":"application/zip","hreflang":null,"title":"BPlan001_5-4","length":null,"rel":"alternate"},{"href":"http://localhost:8083/xplan-wms/services/planwerkwms/planname/BPlan001_5-4","type":null,"hreflang":null,"title":"BPlan001_5-4","length":null,"rel":"planwerkwms"}]}]
diff --git a/xplan-manager/xplan-manager-api/src/test/resources/s3Mock.properties b/xplan-manager/xplan-manager-api/src/test/resources/s3Mock.properties
index 21647337a841afbb48ff5b79ad77c10a152526a1..30c92b7def444a26b2ed608f5d0b7c94bf6fcdd5 100644
--- a/xplan-manager/xplan-manager-api/src/test/resources/s3Mock.properties
+++ b/xplan-manager/xplan-manager-api/src/test/resources/s3Mock.properties
@@ -23,3 +23,5 @@ xplanbox.s3.secretKey=
 xplanbox.s3.bucketName=latlonxpbtest
 xplanbox.s3.region=eu-central-1
 xplanbox.s3.endpoint.url=http://localhost
+
+xplanbox.validation.s3.bucketPublicUrl=http://localhost/test
diff --git a/xplan-manager/xplan-manager-web/.trivyignore b/xplan-manager/xplan-manager-web/.trivyignore
index fd37458902c61457713cb51aaeabb8ae77414843..e3d6fbd587c48b7f55a6766e71d0f0a6c576c6c1 100644
--- a/xplan-manager/xplan-manager-web/.trivyignore
+++ b/xplan-manager/xplan-manager-web/.trivyignore
@@ -1,5 +1,3 @@
-# fixed in Spring 6.0.0
-CVE-2016-1000027
 # from HALE CLI
 CVE-2017-11467
 CVE-2015-7501
diff --git a/xplan-manager/xplan-manager-web/pom.xml b/xplan-manager/xplan-manager-web/pom.xml
index c84776ad06ea7c3eee903ef12f4a1b26c6b56e67..228066f88a0e4abbada4d1774af2281bac2e477f 100644
--- a/xplan-manager/xplan-manager-web/pom.xml
+++ b/xplan-manager/xplan-manager-web/pom.xml
@@ -251,8 +251,13 @@
       <scope>provided</scope>
     </dependency>
     <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.assertj</groupId>
+      <artifactId>assertj-core</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>
diff --git a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/comparator/AlphanumericComparatorTest.java b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/comparator/AlphanumericComparatorTest.java
index cd1b55983c266bf1e0eab959da9774490b5e9714..9e13fc9c5c5c9acbadc20a36288de52c56f0c7c9 100644
--- a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/comparator/AlphanumericComparatorTest.java
+++ b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/comparator/AlphanumericComparatorTest.java
@@ -8,224 +8,170 @@
  * 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%
  */
 package de.latlon.xplan.manager.web.client.comparator;
 
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Description;
-import org.junit.Test;
-
 import java.util.Collections;
 import java.util.List;
 
+import org.junit.jupiter.api.Test;
+
 import static java.util.Arrays.asList;
-import static org.hamcrest.CoreMatchers.anyOf;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
  */
-public class AlphanumericComparatorTest {
+class AlphanumericComparatorTest {
 
 	private final AlphanumericComparator comparator = new AlphanumericComparator();
 
 	@Test
-	public void testCompare_BothNull() {
+	void testCompare_BothNull() {
 		int compare = comparator.compare(null, null);
-		assertThat(compare, is(0));
+		assertEquals(0, compare);
 	}
 
 	@Test
-	public void testCompare_FirstNull() {
+	void testCompare_FirstNull() {
 		int compare = comparator.compare(null, "§1 Nr.2");
-		assertThat(compare, is(1));
+		assertEquals(1, compare);
 	}
 
 	@Test
-	public void testCompare_SecondNull() {
+	void testCompare_SecondNull() {
 		int compare = comparator.compare("§1 Nr.15", null);
-		assertThat(compare, is(-1));
+		assertEquals(-1, compare);
 	}
 
 	@Test
-	public void testCompare_FirstString() {
+	void testCompare_FirstString() {
 		int compare = comparator.compare("ABC", "§1 Nr.2");
-		assertThat(compare, is(greaterThan(0)));
+		assertThat(compare).isGreaterThan(0);
 	}
 
 	@Test
-	public void testCompare_SecondString() {
+	void testCompare_SecondString() {
 		int compare = comparator.compare("§1 Nr.15", "ABC");
-		assertThat(compare, is(-1));
+		assertEquals(-1, compare);
 	}
 
 	@Test
-	public void testCompare_Strings() {
+	void testCompare_Strings() {
 		int compare = comparator.compare("ABC", "DEF");
-		assertThat(compare, is(lessThan(0)));
+		assertThat(compare).isLessThan(0);
 	}
 
 	@Test
-	public void testCompare_Integer() {
+	void testCompare_Integer() {
 		int compare = comparator.compare("10", "2");
-		assertThat(compare, is(1));
+		assertEquals(1, compare);
 	}
 
 	@Test
-	public void testCompare_ParagrahAndNr() {
+	void testCompare_ParagrahAndNr() {
 		int compare = comparator.compare("§1 Nr.15", "§1 Nr.2");
-		assertThat(compare, is(1));
+		assertEquals(1, compare);
 	}
 
 	@Test
-	public void testCompare_Nr() {
+	void testCompare_Nr() {
 		int compare = comparator.compare("1.2", "1.3");
-		assertThat(compare, is(-1));
+		assertEquals(-1, compare);
 	}
 
 	@Test
-	public void testCompare_NrDifferentLength() {
+	void testCompare_NrDifferentLength() {
 		int compare = comparator.compare("1.1", "1.2.9");
-		assertThat(compare, is(-1));
+		assertEquals(-1, compare);
 	}
 
 	@Test
-	public void testCompare_StringWithPipeAndParagraph() {
+	void testCompare_StringWithPipeAndParagraph() {
 		int compare = comparator.compare("§1 Nr.15", "Ende | 1");
-		assertThat(compare, is(-1));
+		assertEquals(-1, compare);
 	}
 
 	@Test
-	public void testCompare_StringAndParagraph() {
+	void testCompare_StringAndParagraph() {
 		int compare = comparator.compare("§3", "SiebzehnPunktVier");
-		assertThat(compare, is(-1));
+		assertEquals(-1, compare);
 	}
 
 	@Test
-	public void testSortList_paragraphsAndNr() {
+	void testSortList_paragraphsAndNr() {
 		List<String> list = asList("§1 Nr.15", "§1", "§1 Nr.2", "Ende | 1", "§3", "SiebzehnPunktVier");
 		Collections.sort(list, comparator);
-		assertThat(list.get(0), is("§1"));
-		assertThat(list.get(1), is("§1 Nr.2"));
-		assertThat(list.get(2), is("§1 Nr.15"));
-		assertThat(list.get(3), is("§3"));
-		assertThat(list.get(4), is("Ende | 1"));
-		assertThat(list.get(5), is("SiebzehnPunktVier"));
+
+		assertThat(list).containsExactly("§1", "§1 Nr.2", "§1 Nr.15", "§3", "Ende | 1", "SiebzehnPunktVier");
 	}
 
 	@Test
-	public void testSortList_numbersOnly() {
+	void testSortList_numbersOnly() {
 		List<String> list = asList("2.1 text", "1.2 text", "2.2 text", "1.1 text");
 		Collections.sort(list, comparator);
-		assertThat(list.get(0), is("1.1 text"));
-		assertThat(list.get(1), is("1.2 text"));
-		assertThat(list.get(2), is("2.1 text"));
-		assertThat(list.get(3), is("2.2 text"));
+		assertThat(list).containsExactly("1.1 text", "1.2 text", "2.1 text", "2.2 text");
 	}
 
 	@Test
-	public void testSortList_charactersOnly() {
+	void testSortList_charactersOnly() {
 		List<String> list = asList("b) text", "d) text", "c) text", "a) text");
 		Collections.sort(list, comparator);
-		assertThat(list.get(0), is("a) text"));
-		assertThat(list.get(1), is("b) text"));
-		assertThat(list.get(2), is("c) text"));
-		assertThat(list.get(3), is("d) text"));
+		assertThat(list).containsExactly("a) text", "b) text", "c) text", "d) text");
 	}
 
 	@Test
-	public void testSortList_charactersAndNumbersMixed() {
+	void testSortList_charactersAndNumbersMixed() {
 		List<String> list = asList("b) text", "2.1 text", "d) text", "1.1 text", "c) text", "a) text", "1.2 text",
 				"2.2 text");
 		Collections.sort(list, comparator);
-		assertThat(list.get(0), is("1.1 text"));
-		assertThat(list.get(1), is("1.2 text"));
-		assertThat(list.get(2), is("2.1 text"));
-		assertThat(list.get(3), is("2.2 text"));
-		assertThat(list.get(4), is("a) text"));
-		assertThat(list.get(5), is("b) text"));
-		assertThat(list.get(6), is("c) text"));
-		assertThat(list.get(7), is("d) text"));
+		assertThat(list).containsExactly("1.1 text", "1.2 text", "2.1 text", "2.2 text", "a) text", "b) text",
+				"c) text", "d) text");
 	}
 
 	@Test
-	public void testSortList_charactersAndNumbers() {
+	void testSortList_charactersAndNumbers() {
 		List<String> list = asList("B text", "A.1.1 text", "A text", "B.1.1 text", "A.1.2 text", "B.1.2 text");
 		Collections.sort(list, comparator);
-		assertThat(list.get(0), is("A text"));
-		assertThat(list.get(1), is("A.1.1 text"));
-		assertThat(list.get(2), is("A.1.2 text"));
-		assertThat(list.get(3), is("B text"));
-		assertThat(list.get(4), is("B.1.1 text"));
-		assertThat(list.get(5), is("B.1.2 text"));
+		assertThat(list).containsExactly("A text", "A.1.1 text", "A.1.2 text", "B text", "B.1.1 text", "B.1.2 text");
 	}
 
 	@Test
-	public void testSortList_NoAndStrings() {
+	void testSortList_NoAndStrings() {
 		List<String> list = asList("[1. | Mit]", "[2. | Im]", "[3. | Im]", "[4. | In]", "[5. | Im]", "[6. | Die]",
 				"[7. | Auf]", "[8. | Auf]", "[9. | Auf]", "[ | Ueber die Festsetzungen nach § 9 Abs. 1 Nr. 25b]",
 				"[10. | Im]", "[11. | Bei]", "[12. | Garagen]", "[13. | Das]",
 				"[ | Rechtliche Grundlagen: Baugesetzbuch (BauGB) Baunutzungsverordnung (BauNVO) in der Fassung vom 23. Januar 1990 ]");
 		Collections.sort(list, comparator);
-		assertThat(list.get(0), is("[1. | Mit]"));
-		assertThat(list.get(1), is("[2. | Im]"));
-		assertThat(list.get(2), is("[3. | Im]"));
-		assertThat(list.get(3), is("[4. | In]"));
-		assertThat(list.get(4), is("[5. | Im]"));
-		assertThat(list.get(5), is("[6. | Die]"));
-		assertThat(list.get(6), is("[7. | Auf]"));
-		assertThat(list.get(7), is("[8. | Auf]"));
-		assertThat(list.get(8), is("[9. | Auf]"));
-		assertThat(list.get(9), is("[10. | Im]"));
-		assertThat(list.get(10), is("[11. | Bei]"));
-		assertThat(list.get(11), is("[12. | Garagen]"));
-		assertThat(list.get(12), is("[13. | Das]"));
-		assertThat(list.get(13), anyOf(is(
-				"[ | Rechtliche Grundlagen: Baugesetzbuch (BauGB) Baunutzungsverordnung (BauNVO) in der Fassung vom 23. Januar 1990 ]"),
-				is("[ | Ueber die Festsetzungen nach § 9 Abs. 1 Nr. 25b]")));
-		assertThat(list.get(14), anyOf(is(
-				"[ | Rechtliche Grundlagen: Baugesetzbuch (BauGB) Baunutzungsverordnung (BauNVO) in der Fassung vom 23. Januar 1990 ]"),
-				is("[ | Ueber die Festsetzungen nach § 9 Abs. 1 Nr. 25b]")));
-	}
-
-	private BaseMatcher<Integer> lessThan(int i) {
-		return new BaseMatcher<Integer>() {
-			@Override
-			public boolean matches(Object o) {
-				int toCompare = (int) o;
-				return toCompare < i;
-			}
-
-			@Override
-			public void describeTo(Description description) {
-
-			}
-		};
-	}
-
-	private BaseMatcher<Integer> greaterThan(int i) {
-		return new BaseMatcher<Integer>() {
-			@Override
-			public boolean matches(Object o) {
-				int toCompare = (int) o;
-				return toCompare > i;
-			}
-
-			@Override
-			public void describeTo(Description description) {
-
-			}
-		};
+		assertThat(list.get(0)).isEqualTo("[1. | Mit]");
+		assertThat(list.get(1)).isEqualTo("[2. | Im]");
+		assertThat(list.get(2)).isEqualTo("[3. | Im]");
+		assertThat(list.get(3)).isEqualTo("[4. | In]");
+		assertThat(list.get(4)).isEqualTo("[5. | Im]");
+		assertThat(list.get(5)).isEqualTo("[6. | Die]");
+		assertThat(list.get(6)).isEqualTo("[7. | Auf]");
+		assertThat(list.get(7)).isEqualTo("[8. | Auf]");
+		assertThat(list.get(8)).isEqualTo("[9. | Auf]");
+		assertThat(list.get(9)).isEqualTo("[10. | Im]");
+		assertThat(list.get(10)).isEqualTo("[11. | Bei]");
+		assertThat(list.get(11)).isEqualTo("[12. | Garagen]");
+		assertThat(list.get(12)).isEqualTo("[13. | Das]");
+		assertThat(list.get(13)).isIn(
+				"[ | Rechtliche Grundlagen: Baugesetzbuch (BauGB) Baunutzungsverordnung (BauNVO) in der Fassung vom 23. Januar 1990 ]",
+				"[ | Ueber die Festsetzungen nach § 9 Abs. 1 Nr. 25b]");
+		assertThat(list.get(14)).isIn(
+				"[ | Rechtliche Grundlagen: Baugesetzbuch (BauGB) Baunutzungsverordnung (BauNVO) in der Fassung vom 23. Januar 1990 ]",
+				"[ | Ueber die Festsetzungen nach § 9 Abs. 1 Nr. 25b]");
 	}
 
 }
diff --git a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/comparator/ColumnComparatorTest.java b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/comparator/ColumnComparatorTest.java
index 8b24a7eafccc65af2caade58de43a7f9c4fcb683..7961414dbfc13bc910d6f9df521d54d8c987b6e3 100644
--- a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/comparator/ColumnComparatorTest.java
+++ b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/comparator/ColumnComparatorTest.java
@@ -21,16 +21,15 @@
 package de.latlon.xplan.manager.web.client.comparator;
 
 import de.latlon.xplan.manager.web.shared.XPlan;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import java.util.Date;
 
 import static de.latlon.xplan.manager.web.client.gui.PlanListColumnType.IMPORTDATE;
 import static de.latlon.xplan.manager.web.client.gui.PlanListColumnType.NAME;
 import static de.latlon.xplan.manager.web.client.gui.PlanListColumnType.TYPE;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 /**
  * Tests for {@link ColumnComparator}.
@@ -38,7 +37,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
  * @author <a href="mailto:stenger@lat-lon.de">Dirk Stenger</a>
  * @version $Revision: $, $Date: $
  */
-public class ColumnComparatorTest {
+class ColumnComparatorTest {
 
 	private XPlan plan1;
 
@@ -48,8 +47,8 @@ public class ColumnComparatorTest {
 
 	private XPlan plan2;
 
-	@Before
-	public void setup() {
+	@BeforeEach
+	void setup() {
 		plan1 = new XPlan("name1", "1", "type1");
 		plan1Equal = new XPlan("name1", "1", "type1");
 		plan1Null = new XPlan("name2", "2", null);
@@ -57,61 +56,61 @@ public class ColumnComparatorTest {
 	}
 
 	@Test
-	public void testCompareShouldBeSmaller() throws Exception {
+	void testCompareShouldBeSmaller() throws Exception {
 		ColumnComparator comparator = new ColumnComparator(NAME);
 		int result = comparator.compare(plan1, plan2);
 
-		assertThat(result, is(-1));
+		assertEquals(-1, result);
 	}
 
 	@Test
-	public void testCompareShouldBeGreater() throws Exception {
+	void testCompareShouldBeGreater() throws Exception {
 		ColumnComparator comparator = new ColumnComparator(NAME);
 		int result = comparator.compare(plan2, plan1);
 
-		assertThat(result, is(1));
+		assertEquals(1, result);
 	}
 
 	@Test
-	public void testCompareShouldBeEqual() throws Exception {
+	void testCompareShouldBeEqual() throws Exception {
 		ColumnComparator comparator = new ColumnComparator(NAME);
 		int result = comparator.compare(plan1, plan1Equal);
 
-		assertThat(result, is(0));
+		assertEquals(0, result);
 	}
 
 	@Test
-	public void testCompareWithNullShouldBeSmaller() throws Exception {
+	void testCompareWithNullShouldBeSmaller() throws Exception {
 		ColumnComparator comparator = new ColumnComparator(TYPE);
 		int result = comparator.compare(plan1Null, plan1);
 
-		assertThat(result, is(-1));
+		assertEquals(-1, result);
 	}
 
 	@Test
-	public void testCompareWithNullShouldBeGreater() throws Exception {
+	void testCompareWithNullShouldBeGreater() throws Exception {
 		ColumnComparator comparator = new ColumnComparator(TYPE);
 		int result = comparator.compare(plan1, plan1Null);
 
-		assertThat(result, is(1));
+		assertEquals(1, result);
 	}
 
 	@Test
-	public void testCompareWithNullShouldBeEqual() throws Exception {
+	void testCompareWithNullShouldBeEqual() throws Exception {
 		ColumnComparator comparator = new ColumnComparator(NAME);
 		int result = comparator.compare(plan1Null, plan1Null);
 
-		assertThat(result, is(0));
+		assertEquals(0, result);
 	}
 
 	@Test
-	public void testCompareDate() throws Exception {
+	void testCompareDate() throws Exception {
 		plan1.setImportDate(new Date(112014));
 		plan2.setImportDate(new Date(212014));
 		ColumnComparator comparator = new ColumnComparator(IMPORTDATE);
 		int result = comparator.compare(plan1, plan2);
 
-		assertThat(result, is(-1));
+		assertEquals(-1, result);
 	}
 
 }
diff --git a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/filter/FreeTextFilterTest.java b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/filter/FreeTextFilterTest.java
index cb87e704b857ef28a59339e8962818ad53cf6f96..2195fe7088b9786b40f46ad2d75c598e26879c89 100644
--- a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/filter/FreeTextFilterTest.java
+++ b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/filter/FreeTextFilterTest.java
@@ -21,158 +21,159 @@
 package de.latlon.xplan.manager.web.client.filter;
 
 import de.latlon.xplan.manager.web.shared.XPlan;
-import org.junit.Ignore;
-import org.junit.Test;
 
 import static de.latlon.xplan.manager.web.client.gui.PlanListColumnType.ID;
 import static de.latlon.xplan.manager.web.client.gui.PlanListColumnType.LEGISLATIONSTATUS;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
 
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz</a>
  * @version $Revision: $, $Date: $
  */
-public class FreeTextFilterTest {
+class FreeTextFilterTest {
 
 	@Test
-	public void testIsMatchingWithNullStringShouldReturnTrue() throws Exception {
+	void testIsMatchingWithNullStringShouldReturnTrue() throws Exception {
 		FreeTextFilter freeTextFilter = new FreeTextFilter(null);
 
 		XPlan plan = createPlan();
 		boolean matching = freeTextFilter.isMatching(plan);
 
-		assertThat(matching, is(true));
+		assertTrue(matching);
 	}
 
 	@Test
-	public void testIsMatchingWithEmptyStringShouldReturnTrue() throws Exception {
+	void testIsMatchingWithEmptyStringShouldReturnTrue() throws Exception {
 		FreeTextFilter freeTextFilter = new FreeTextFilter("");
 
 		XPlan plan = createPlan();
 		boolean matching = freeTextFilter.isMatching(plan);
 
-		assertThat(matching, is(true));
+		assertTrue(matching);
 	}
 
 	@Test
-	public void testIsMatchingWithWhiteSpaceStringShouldReturnTrue() throws Exception {
+	void testIsMatchingWithWhiteSpaceStringShouldReturnTrue() throws Exception {
 		FreeTextFilter freeTextFilter = new FreeTextFilter(" ");
 
 		XPlan plan = createPlan();
 		boolean matching = freeTextFilter.isMatching(plan);
 
-		assertThat(matching, is(true));
+		assertTrue(matching);
 	}
 
 	@Test
-	public void testIsMatchingWithExactCategoryShouldReturnTrue() throws Exception {
+	void testIsMatchingWithExactCategoryShouldReturnTrue() throws Exception {
 		FreeTextFilter freeTextFilter = new FreeTextFilter("name");
 
 		XPlan plan = createPlan();
 		boolean matching = freeTextFilter.isMatching(plan);
 
-		assertThat(matching, is(true));
+		assertTrue(matching);
 	}
 
 	@Test
-	public void testIsMatchingWithLowerUpperCaseLegislationStatusShouldReturnTrue() throws Exception {
+	void testIsMatchingWithLowerUpperCaseLegislationStatusShouldReturnTrue() throws Exception {
 		FreeTextFilter freeTextFilter = new FreeTextFilter("legislaTionsTAtus");
 
 		XPlan plan = createPlan();
 		boolean matching = freeTextFilter.isMatching(plan);
 
-		assertThat(matching, is(true));
+		assertTrue(matching);
 	}
 
 	@Test
-	public void testIsMatchingWithParAdditionaltypeShouldReturnTrue() throws Exception {
+	void testIsMatchingWithParAdditionaltypeShouldReturnTrue() throws Exception {
 		FreeTextFilter freeTextFilter = new FreeTextFilter("itio");
 
 		XPlan plan = createPlan();
 		boolean matching = freeTextFilter.isMatching(plan);
 
-		assertThat(matching, is(true));
+		assertTrue(matching);
 	}
 
 	@Test
-	public void testIsMatchingWithWildcardShouldReturnTrue() throws Exception {
+	void testIsMatchingWithWildcardShouldReturnTrue() throws Exception {
 		FreeTextFilter freeTextFilter = new FreeTextFilter("legis*STATUS");
 
 		XPlan plan = createPlan();
 		boolean matching = freeTextFilter.isMatching(plan);
 
-		assertThat(matching, is(true));
+		assertTrue(matching);
 	}
 
 	@Test
-	public void testIsMatchingWithWildcardInBeginningShouldReturnTrue() throws Exception {
+	void testIsMatchingWithWildcardInBeginningShouldReturnTrue() throws Exception {
 		FreeTextFilter freeTextFilter = new FreeTextFilter("*isla");
 
 		XPlan plan = createPlan();
 		boolean matching = freeTextFilter.isMatching(plan);
 
-		assertThat(matching, is(true));
+		assertTrue(matching);
 	}
 
 	@Test
-	public void testIsMatchingWithWildcardOnlyShouldReturnTrue() throws Exception {
+	void testIsMatchingWithWildcardOnlyShouldReturnTrue() throws Exception {
 		FreeTextFilter freeTextFilter = new FreeTextFilter("leg*STA*US");
 
 		XPlan plan = createPlan();
 		boolean matching = freeTextFilter.isMatching(plan);
 
-		assertThat(matching, is(true));
+		assertTrue(matching);
 	}
 
 	@Test
-	public void testIsMatchingWithMultipleWildcardsShouldReturnTrue() throws Exception {
+	void testIsMatchingWithMultipleWildcardsShouldReturnTrue() throws Exception {
 		FreeTextFilter freeTextFilter = new FreeTextFilter("*");
 
 		XPlan plan = createPlan();
 		boolean matching = freeTextFilter.isMatching(plan);
 
-		assertThat(matching, is(true));
+		assertTrue(matching);
 	}
 
-	public void testIsMatchingWithWildcardShoudReturnFalse() throws Exception {
+	void testIsMatchingWithWildcardShoudReturnFalse() throws Exception {
 		FreeTextFilter freeTextFilter = new FreeTextFilter("legislation*ion");
 
 		XPlan plan = createPlan();
 		boolean matching = freeTextFilter.isMatching(plan);
 
-		assertThat(matching, is(false));
+		assertFalse(matching);
 	}
 
-	@Ignore("Test currently fails as a gwt client class (here DateTimeFormat) cannot be used.")
+	@Disabled("Test currently fails as a gwt client class (here DateTimeFormat) cannot be used.")
 	@Test
-	public void testIsMatchingWithUnavailableStringShouldReturnFalse() throws Exception {
+	void testIsMatchingWithUnavailableStringShouldReturnFalse() throws Exception {
 		FreeTextFilter freeTextFilter = new FreeTextFilter("SeArch");
 
 		XPlan plan = createPlan();
 		boolean matching = freeTextFilter.isMatching(plan);
 
-		assertThat(matching, is(false));
+		assertFalse(matching);
 	}
 
 	@Test
-	public void testIsMatchingInColumnlegislationShouldReturnTrue() throws Exception {
+	void testIsMatchingInColumnlegislationShouldReturnTrue() throws Exception {
 		FreeTextFilter freeTextFilter = new FreeTextFilter(LEGISLATIONSTATUS, "leg*StaT");
 
 		XPlan plan = createPlan();
 		boolean matching = freeTextFilter.isMatching(plan);
 
-		assertThat(matching, is(true));
+		assertTrue(matching);
 	}
 
 	@Test
-	public void testIsMatchingInColumnIdShouldReturnFalse() throws Exception {
+	void testIsMatchingInColumnIdShouldReturnFalse() throws Exception {
 		FreeTextFilter freeTextFilter = new FreeTextFilter(ID, "leg*StaT");
 
 		XPlan plan = createPlan();
 		boolean matching = freeTextFilter.isMatching(plan);
 
-		assertThat(matching, is(false));
+		assertFalse(matching);
 	}
 
 	private XPlan createPlan() {
diff --git a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/filter/PlanStatusFilterTest.java b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/filter/PlanStatusFilterTest.java
index 3d01ccc4c350f66bbdb7f06f93090bfcea441e68..b294d85c0ba85c10d164470b8f8503bdead7c5e3 100644
--- a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/filter/PlanStatusFilterTest.java
+++ b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/filter/PlanStatusFilterTest.java
@@ -22,57 +22,58 @@ package de.latlon.xplan.manager.web.client.filter;
 
 import de.latlon.xplan.manager.web.shared.PlanStatus;
 import de.latlon.xplan.manager.web.shared.XPlan;
-import org.junit.Test;
 
 import static de.latlon.xplan.manager.web.shared.PlanStatus.FESTGESTELLT;
 import static de.latlon.xplan.manager.web.shared.PlanStatus.IN_AUFSTELLUNG;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
 
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz</a>
  * @version $Revision: $, $Date: $
  */
-public class PlanStatusFilterTest {
+class PlanStatusFilterTest {
 
 	@Test
-	public void testIsMatchingWithNullStringShouldReturnTrue() throws Exception {
+	void testIsMatchingWithNullStringShouldReturnTrue() throws Exception {
 		PlanStatusFilter planStatusFilter = new PlanStatusFilter(null);
 
 		XPlan plan = createPlan(FESTGESTELLT);
 		boolean matching = planStatusFilter.isMatching(plan);
 
-		assertThat(matching, is(true));
+		assertTrue(matching);
 	}
 
 	@Test
-	public void testIsMatchingWithEmptyStringShouldReturnTrue() throws Exception {
+	void testIsMatchingWithEmptyStringShouldReturnTrue() throws Exception {
 		PlanStatusFilter planStatusFilter = new PlanStatusFilter("");
 
 		XPlan plan = createPlan(FESTGESTELLT);
 		boolean matching = planStatusFilter.isMatching(plan);
 
-		assertThat(matching, is(true));
+		assertTrue(matching);
 	}
 
 	@Test
-	public void testIsMatchingWithNotMatchingStringShouldReturnTrue() throws Exception {
+	void testIsMatchingWithNotMatchingStringShouldReturnTrue() throws Exception {
 		PlanStatusFilter planStatusFilter = new PlanStatusFilter(IN_AUFSTELLUNG.getMessage());
 
 		XPlan plan = createPlan(FESTGESTELLT);
 		boolean matching = planStatusFilter.isMatching(plan);
 
-		assertThat(matching, is(false));
+		assertFalse(matching);
 	}
 
 	@Test
-	public void testIsMatchingWithMatchingStringShouldReturnTrue() throws Exception {
+	void testIsMatchingWithMatchingStringShouldReturnTrue() throws Exception {
 		PlanStatusFilter planStatusFilter = new PlanStatusFilter(FESTGESTELLT.getMessage());
 
 		XPlan plan = createPlan(FESTGESTELLT);
 		boolean matching = planStatusFilter.isMatching(plan);
 
-		assertThat(matching, is(true));
+		assertTrue(matching);
 	}
 
 	private XPlan createPlan(PlanStatus planStatus) {
diff --git a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/utils/DateTimeUtilsTest.java b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/utils/DateTimeUtilsTest.java
index f85910148468d639ff68f0477494804c76c204c6..7c7e544c6a559133d79c155ea49f984794a6fe6c 100644
--- a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/utils/DateTimeUtilsTest.java
+++ b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/utils/DateTimeUtilsTest.java
@@ -20,96 +20,96 @@
  */
 package de.latlon.xplan.manager.web.client.utils;
 
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.Date;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz</a>
  * @version $Revision: $, $Date: $
  */
-public class DateTimeUtilsTest {
+class DateTimeUtilsTest {
 
 	@Test
-	public void testIsCurrentDateTimeBetween() throws Exception {
+	void testIsCurrentDateTimeBetween() throws Exception {
 		long currentTimeMillis = System.currentTimeMillis();
 		Date startDateTime = new Date(currentTimeMillis - 1000);
 		Date endDateTime = new Date(currentTimeMillis + 1000000000);
 		boolean isCurrentDateTimeBetween = DateTimeUtils.isCurrentDateTimeBetween(startDateTime, endDateTime);
 
-		assertThat(isCurrentDateTimeBetween, is(true));
+		assertTrue(isCurrentDateTimeBetween);
 	}
 
 	@Test
-	public void testIsCurrentDateTimeBetweenStartAndEndIsNull() throws Exception {
+	void testIsCurrentDateTimeBetweenStartAndEndIsNull() throws Exception {
 		Date startDateTime = null;
 		Date endDateTime = null;
 		boolean isCurrentDateTimeBetween = DateTimeUtils.isCurrentDateTimeBetween(startDateTime, endDateTime);
 
-		assertThat(isCurrentDateTimeBetween, is(true));
+		assertTrue(isCurrentDateTimeBetween);
 	}
 
 	@Test
-	public void testIsCurrentDateTimeBetweenStartIsNull() throws Exception {
+	void testIsCurrentDateTimeBetweenStartIsNull() throws Exception {
 		long currentTimeMillis = System.currentTimeMillis();
 		Date startDateTime = null;
 		Date endDateTime = new Date(currentTimeMillis + 1000000000);
 		boolean isCurrentDateTimeBetween = DateTimeUtils.isCurrentDateTimeBetween(startDateTime, endDateTime);
 
-		assertThat(isCurrentDateTimeBetween, is(true));
+		assertTrue(isCurrentDateTimeBetween);
 	}
 
 	@Test
-	public void testIsCurrentDateTimeBetweenStartIsNullCurrentIsAfterEnd() throws Exception {
+	void testIsCurrentDateTimeBetweenStartIsNullCurrentIsAfterEnd() throws Exception {
 		long currentTimeMillis = System.currentTimeMillis();
 		Date startDateTime = null;
 		Date endDateTime = new Date(currentTimeMillis - 1000);
 		boolean isCurrentDateTimeBetween = DateTimeUtils.isCurrentDateTimeBetween(startDateTime, endDateTime);
 
-		assertThat(isCurrentDateTimeBetween, is(false));
+		assertFalse(isCurrentDateTimeBetween);
 	}
 
 	@Test
-	public void testIsCurrentDateTimeBetweenEndIsNull() throws Exception {
+	void testIsCurrentDateTimeBetweenEndIsNull() throws Exception {
 		long currentTimeMillis = System.currentTimeMillis();
 		Date startDateTime = new Date(currentTimeMillis - 1000);
 		Date endDateTime = null;
 		boolean isCurrentDateTimeBetween = DateTimeUtils.isCurrentDateTimeBetween(startDateTime, endDateTime);
 
-		assertThat(isCurrentDateTimeBetween, is(true));
+		assertTrue(isCurrentDateTimeBetween);
 	}
 
 	@Test
-	public void testIsCurrentDateTimeBetweenEndIsNullCurrentIsBeforeStart() throws Exception {
+	void testIsCurrentDateTimeBetweenEndIsNullCurrentIsBeforeStart() throws Exception {
 		long currentTimeMillis = System.currentTimeMillis();
 		Date startDateTime = new Date(currentTimeMillis + 1000000000);
 		Date endDateTime = null;
 		boolean isCurrentDateTimeBetween = DateTimeUtils.isCurrentDateTimeBetween(startDateTime, endDateTime);
 
-		assertThat(isCurrentDateTimeBetween, is(false));
+		assertFalse(isCurrentDateTimeBetween);
 	}
 
 	@Test
-	public void testIsCurrentDateTimeBetweenCurrentIsAfter() throws Exception {
+	void testIsCurrentDateTimeBetweenCurrentIsAfter() throws Exception {
 		long currentTimeMillis = System.currentTimeMillis();
 		Date startDateTime = new Date(currentTimeMillis - 10000);
 		Date endDateTime = new Date(currentTimeMillis - 1000);
 		boolean isCurrentDateTimeBetween = DateTimeUtils.isCurrentDateTimeBetween(startDateTime, endDateTime);
 
-		assertThat(isCurrentDateTimeBetween, is(false));
+		assertFalse(isCurrentDateTimeBetween);
 	}
 
 	@Test
-	public void testIsCurrentDateTimeBetweenCurrentIsBefore() throws Exception {
+	void testIsCurrentDateTimeBetweenCurrentIsBefore() throws Exception {
 		long currentTimeMillis = System.currentTimeMillis();
 		Date startDateTime = new Date(currentTimeMillis + 100000000);
 		Date endDateTime = new Date(currentTimeMillis + 1000000000);
 		boolean isCurrentDateTimeBetween = DateTimeUtils.isCurrentDateTimeBetween(startDateTime, endDateTime);
 
-		assertThat(isCurrentDateTimeBetween, is(false));
+		assertFalse(isCurrentDateTimeBetween);
 	}
 
 }
diff --git a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/utils/ReferenceNameUtilsTest.java b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/utils/ReferenceNameUtilsTest.java
index f7ef7f5be32dbf938930af091d506f011e9e482b..2db8e7000d7d0dd8b3e7eaebd0bbbd6317e1f269 100644
--- a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/utils/ReferenceNameUtilsTest.java
+++ b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/utils/ReferenceNameUtilsTest.java
@@ -20,104 +20,103 @@
  */
 package de.latlon.xplan.manager.web.client.utils;
 
-import org.junit.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
 
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.hamcrest.MatcherAssert.assertThat;
+import org.junit.jupiter.api.Test;
 
-public class ReferenceNameUtilsTest {
+class ReferenceNameUtilsTest {
 
 	@Test
-	public void testThatParseFilenameFromUrlWithQueryParameter() {
+	void testThatParseFilenameFromUrlWithQueryParameter() {
 		String url = "https://example.com/path/to/file.txt?abc=1&xyz=abc.pdf";
 		String filename = ReferenceNameUtils.extractFilenameFromUrl(url);
-		assertThat(filename, is("file"));
+		assertEquals("file", filename);
 	}
 
 	@Test
-	public void testThatParseFilenameFromUrlWithQueryParameterWithoutFile() {
+	void testThatParseFilenameFromUrlWithQueryParameterWithoutFile() {
 		String url = "https://example.com/path/to?abc=1&xyz=abc.pdf";
 		String filename = ReferenceNameUtils.extractFilenameFromUrl(url);
-		assertThat(filename, is("abc=1&xyz=abc.pdf"));
+		assertEquals("abc=1&xyz=abc.pdf", filename);
 	}
 
 	@Test
-	public void testThatParseFilenameFromUrlWithQueryParameterWithoutFile1() {
+	void testThatParseFilenameFromUrlWithQueryParameterWithoutFile1() {
 		String url = "https://example.com/path/to?abc=1&xyz=abc";
 		String filename = ReferenceNameUtils.extractFilenameFromUrl(url);
-		assertThat(filename, is("abc=1&xyz=abc"));
+		assertEquals("abc=1&xyz=abc", filename);
 	}
 
 	@Test
-	public void testThatParseFilenameFromUrlWithQueryParameterWithTrailingSlash() {
+	void testThatParseFilenameFromUrlWithQueryParameterWithTrailingSlash() {
 		String url = "https://example.com/path/to/?abc=1&xyz=abc.pdf";
 		String filename = ReferenceNameUtils.extractFilenameFromUrl(url);
-		assertThat(filename, is("abc=1&xyz=abc.pdf"));
+		assertEquals("abc=1&xyz=abc.pdf", filename);
 	}
 
 	@Test
-	public void testThatParseFilenameFromUrlWithTrailingQuestionmark() {
+	void testThatParseFilenameFromUrlWithTrailingQuestionmark() {
 		String url = "https://example.com/path/to/file.txt?";
 		String filename = ReferenceNameUtils.extractFilenameFromUrl(url);
-		assertThat(filename, is("file"));
+		assertEquals("file", filename);
 	}
 
 	@Test
-	public void testThatParseFilenameFromUrlWithoutExtensionWithTrailingQuestionmark() {
+	void testThatParseFilenameFromUrlWithoutExtensionWithTrailingQuestionmark() {
 		String url = "https://example.com/path/to/file?";
 		String filename = ReferenceNameUtils.extractFilenameFromUrl(url);
-		assertThat(filename, is("file"));
+		assertEquals("file", filename);
 	}
 
 	@Test
-	public void testThatParseFilenameFromUrlWithoutExtension() {
+	void testThatParseFilenameFromUrlWithoutExtension() {
 		String url = "https://example.com/path/to/file";
 		String filename = ReferenceNameUtils.extractFilenameFromUrl(url);
-		assertThat(filename, is("file"));
+		assertEquals("file", filename);
 	}
 
 	@Test
-	public void testThatParseFilenameFromUrlWithExtension() {
+	void testThatParseFilenameFromUrlWithExtension() {
 		String url = "https://example.com/path/to/file.txt";
 		String filename = ReferenceNameUtils.extractFilenameFromUrl(url);
-		assertThat(filename, is("file"));
+		assertEquals("file", filename);
 	}
 
 	@Test
-	public void testThatParseFilenameFromUrlWithTrailingSlash() {
+	void testThatParseFilenameFromUrlWithTrailingSlash() {
 		String url = "https://example.com/path/to/file.txt/";
 		String filename = ReferenceNameUtils.extractFilenameFromUrl(url);
-		assertThat(filename, is("file"));
+		assertEquals("file", filename);
 	}
 
 	@Test
-	public void testThatParseFilenameFromUrlWithoutPathAndFile() {
+	void testThatParseFilenameFromUrlWithoutPathAndFile() {
 		String url = "https://example.com/";
 		String filename = ReferenceNameUtils.extractFilenameFromUrl(url);
-		assertThat(filename, is("example"));
+		assertEquals("example", filename);
 
 	}
 
 	@Test
-	public void testThatParseFilenameFromUrlWithCredentials() {
+	void testThatParseFilenameFromUrlWithCredentials() {
 		String url = "https://foo@bar:example.com/path/to/file.txt";
 		String filename = ReferenceNameUtils.extractFilenameFromUrl(url);
-		assertThat(filename, is("file"));
+		assertEquals("file", filename);
 	}
 
 	@Test
-	public void testThatParseFilenameFromUrlWithEmptyString() {
+	void testThatParseFilenameFromUrlWithEmptyString() {
 		String url = "";
 		String filename = ReferenceNameUtils.extractFilenameFromUrl(url);
-		assertThat(filename, nullValue());
+		assertNull(filename);
 	}
 
 	@Test
-	public void testThatParseFilenameFromFileWithExtension() {
+	void testThatParseFilenameFromFileWithExtension() {
 		String file = "file.txt";
 		String filename = ReferenceNameUtils.extractFilenameFromFile(file);
-		assertThat(filename, is("file"));
+		assertEquals("file", filename);
 	}
 
 }
diff --git a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/utils/WmsUrlUtilsTest.java b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/utils/WmsUrlUtilsTest.java
index 7b1099812fa8827e484fcd245f5d54c51faec382..73ff249dd61b29225ead3ef668c4048582ac928f 100644
--- a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/utils/WmsUrlUtilsTest.java
+++ b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/client/utils/WmsUrlUtilsTest.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%
@@ -23,11 +23,10 @@ package de.latlon.xplan.manager.web.client.utils;
 import static de.latlon.xplan.manager.web.shared.PlanStatus.ARCHIVIERT;
 import static de.latlon.xplan.manager.web.shared.PlanStatus.FESTGESTELLT;
 import static de.latlon.xplan.manager.web.shared.PlanStatus.IN_AUFSTELLUNG;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.Mockito.when;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 
 import de.latlon.xplan.manager.web.shared.MapPreviewConfiguration;
@@ -36,174 +35,175 @@ import de.latlon.xplan.manager.web.shared.MapPreviewConfiguration;
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz</a>
  * @version $Revision: $, $Date: $
  */
-public class WmsUrlUtilsTest {
+class WmsUrlUtilsTest {
 
 	@Test
-	public void testDetermineWmsUrlWithEndpointAndQuestionmark() throws Exception {
+	void testDetermineWmsUrlWithEndpointAndQuestionmark() throws Exception {
 		String wmsBaseUrl = "http://localhost:8080/xplan-wms/services/wms?";
 		String wmsUrl = WmsUrlUtils.determineWmsUrl(IN_AUFSTELLUNG, mockConfiguration(wmsBaseUrl));
 
-		assertThat(wmsUrl, is(wmsBaseUrl));
+		assertEquals(wmsBaseUrl, wmsUrl);
 	}
 
 	@Test
-	public void testDetermineWmsUrlWithEndpoint() throws Exception {
+	void testDetermineWmsUrlWithEndpoint() throws Exception {
 		String wmsBaseUrl = "http://localhost:8080/xplan-wms/services/wms";
 		String wmsUrl = WmsUrlUtils.determineWmsUrl(IN_AUFSTELLUNG, mockConfiguration(wmsBaseUrl));
 
-		assertThat(wmsUrl, is("http://localhost:8080/xplan-wms/services/wms?"));
+		assertEquals("http://localhost:8080/xplan-wms/services/wms?", wmsUrl);
 	}
 
 	@Test
-	public void testDetermineWmsUrlWithoutEndpointAndPlanStatusFestgestellt() throws Exception {
+	void testDetermineWmsUrlWithoutEndpointAndPlanStatusFestgestellt() throws Exception {
 		String wmsBaseUrl = "http://localhost:8080/xplan-wms/services/";
 		String wmsUrl = WmsUrlUtils.determineWmsUrl(FESTGESTELLT, mockConfiguration(wmsBaseUrl));
 
-		assertThat(wmsUrl, is("http://localhost:8080/xplan-wms/services/wms?"));
+		assertEquals("http://localhost:8080/xplan-wms/services/wms?", wmsUrl);
 	}
 
 	@Test
-	public void testDetermineWmsUrlWithoutEndpointAndPlanStatusInAufstellung() throws Exception {
+	void testDetermineWmsUrlWithoutEndpointAndPlanStatusInAufstellung() throws Exception {
 		String wmsBaseUrl = "http://localhost:8080/xplan-wms/services/";
 		String wmsUrl = WmsUrlUtils.determineWmsUrl(IN_AUFSTELLUNG, mockConfiguration(wmsBaseUrl));
 
-		assertThat(wmsUrl, is("http://localhost:8080/xplan-wms/services/wmspre?"));
+		assertEquals("http://localhost:8080/xplan-wms/services/wmspre?", wmsUrl);
 	}
 
 	@Test
-	public void testDetermineWmsUrlWithoutEndpointAndNullPlanStatus() throws Exception {
+	void testDetermineWmsUrlWithoutEndpointAndNullPlanStatus() throws Exception {
 		String wmsBaseUrl = "http://localhost:8080/xplan-wms/services/";
 		String wmsUrl = WmsUrlUtils.determineWmsUrl(null, mockConfiguration(wmsBaseUrl));
 
-		assertThat(wmsUrl, is("http://localhost:8080/xplan-wms/services/wms?"));
+		assertEquals("http://localhost:8080/xplan-wms/services/wms?", wmsUrl);
 	}
 
 	@Test
-	public void testDetermineWmsUrlWithoutEndpointAndSlashAndPlanStatusFestgestellt() throws Exception {
+	void testDetermineWmsUrlWithoutEndpointAndSlashAndPlanStatusFestgestellt() throws Exception {
 		String wmsBaseUrl = "http://localhost:8080/xplan-wms/services";
 		String wmsUrl = WmsUrlUtils.determineWmsUrl(FESTGESTELLT, mockConfiguration(wmsBaseUrl));
 
-		assertThat(wmsUrl, is("http://localhost:8080/xplan-wms/services/wms?"));
+		assertEquals("http://localhost:8080/xplan-wms/services/wms?", wmsUrl);
 	}
 
 	@Test
-	public void testDetermineWmsUrlWithoutEndpointAndSlashAndPlanStatusInAufstellung() throws Exception {
+	void testDetermineWmsUrlWithoutEndpointAndSlashAndPlanStatusInAufstellung() throws Exception {
 		String wmsBaseUrl = "http://localhost:8080/xplan-wms/services";
 		String wmsUrl = WmsUrlUtils.determineWmsUrl(IN_AUFSTELLUNG, mockConfiguration(wmsBaseUrl));
 
-		assertThat(wmsUrl, is("http://localhost:8080/xplan-wms/services/wmspre?"));
+		assertEquals("http://localhost:8080/xplan-wms/services/wmspre?", wmsUrl);
 	}
 
 	@Test
-	public void testDetermineWmsUrlWithoutEndpointAndSlashAndNullPlanStatus() throws Exception {
+	void testDetermineWmsUrlWithoutEndpointAndSlashAndNullPlanStatus() throws Exception {
 		String wmsBaseUrl = "http://localhost:8080/xplan-wms/services";
 		String wmsUrl = WmsUrlUtils.determineWmsUrl(null, mockConfiguration(wmsBaseUrl));
 
-		assertThat(wmsUrl, is("http://localhost:8080/xplan-wms/services/wms?"));
+		assertEquals("http://localhost:8080/xplan-wms/services/wms?", wmsUrl);
 	}
 
 	@Test
-	public void testDetermineWmsUrlWithoutEndpointAndPlanStatusFestgestelltNoWmsEndpointConfigured() throws Exception {
+	void testDetermineWmsUrlWithoutEndpointAndPlanStatusFestgestelltNoWmsEndpointConfigured() throws Exception {
 		String wmsBaseUrl = "http://localhost:8080/xplan-wms/services/";
 		String wmsUrl = WmsUrlUtils.determineWmsUrl(FESTGESTELLT, mockConfigurationWithoutWmsEndpoint(wmsBaseUrl));
 
-		assertThat(wmsUrl, is("http://localhost:8080/xplan-wms/services/wmspre?"));
+		assertEquals("http://localhost:8080/xplan-wms/services/wmspre?", wmsUrl);
 	}
 
 	@Test
-	public void testDetermineWmsUrlWithoutEndpointAndPlanStatusInAufstellungNoWmsEndpointConfigured() throws Exception {
+	void testDetermineWmsUrlWithoutEndpointAndPlanStatusInAufstellungNoWmsEndpointConfigured() throws Exception {
 		String wmsBaseUrl = "http://localhost:8080/xplan-wms/services/";
 		String wmsUrl = WmsUrlUtils.determineWmsUrl(IN_AUFSTELLUNG, mockConfigurationWithoutWmsEndpoint(wmsBaseUrl));
 
-		assertThat(wmsUrl, is("http://localhost:8080/xplan-wms/services/wmspre?"));
+		assertEquals("http://localhost:8080/xplan-wms/services/wmspre?", wmsUrl);
 	}
 
 	@Test
-	public void testDetermineWmsUrlWithoutEndpointAndNullPlanStatusNoWmsEndpointConfigured() throws Exception {
+	void testDetermineWmsUrlWithoutEndpointAndNullPlanStatusNoWmsEndpointConfigured() throws Exception {
 		String wmsBaseUrl = "http://localhost:8080/xplan-wms/services/";
 		String wmsUrl = WmsUrlUtils.determineWmsUrl(null, mockConfigurationWithoutWmsEndpoint(wmsBaseUrl));
 
-		assertThat(wmsUrl, is("http://localhost:8080/xplan-wms/services/wmspre?"));
+		assertEquals("http://localhost:8080/xplan-wms/services/wmspre?", wmsUrl);
 	}
 
 	@Test
-	public void testDetermineWmsUrlWithoutEndpointAndPlanStatusFestgestelltNoWmsPreEndpointConfigured()
-			throws Exception {
+	void testDetermineWmsUrlWithoutEndpointAndPlanStatusFestgestelltNoWmsPreEndpointConfigured() throws Exception {
 		String wmsBaseUrl = "http://localhost:8080/xplan-wms/services/";
 		String wmsUrl = WmsUrlUtils.determineWmsUrl(FESTGESTELLT, mockConfigurationWithoutWmsPreEndpoint(wmsBaseUrl));
 
-		assertThat(wmsUrl, is("http://localhost:8080/xplan-wms/services/wms?"));
+		assertEquals("http://localhost:8080/xplan-wms/services/wms?", wmsUrl);
 	}
 
 	@Test
-	public void testDetermineWmsUrlWithoutEndpointAndPlanStatusInAufstellungNoWmsPreEndpointConfigured()
-			throws Exception {
+	void testDetermineWmsUrlWithoutEndpointAndPlanStatusInAufstellungNoWmsPreEndpointConfigured() throws Exception {
 		String wmsBaseUrl = "http://localhost:8080/xplan-wms/services/";
 		String wmsUrl = WmsUrlUtils.determineWmsUrl(IN_AUFSTELLUNG, mockConfigurationWithoutWmsPreEndpoint(wmsBaseUrl));
 
-		assertThat(wmsUrl, is("http://localhost:8080/xplan-wms/services/wms?"));
+		assertEquals("http://localhost:8080/xplan-wms/services/wms?", wmsUrl);
 	}
 
 	@Test
-	public void testDetermineWmsUrlWithoutEndpointAndNullPlanStatusNoWmsPreEndpointConfigured() throws Exception {
+	void testDetermineWmsUrlWithoutEndpointAndNullPlanStatusNoWmsPreEndpointConfigured() throws Exception {
 		String wmsBaseUrl = "http://localhost:8080/xplan-wms/services/";
 		String wmsUrl = WmsUrlUtils.determineWmsUrl(null, mockConfigurationWithoutWmsPreEndpoint(wmsBaseUrl));
 
-		assertThat(wmsUrl, is("http://localhost:8080/xplan-wms/services/wms?"));
+		assertEquals("http://localhost:8080/xplan-wms/services/wms?", wmsUrl);
 	}
 
 	@Test
-	public void testDetermineWmsUrlWithoutEndpointAndPlanStatusFestgestelltNoEndpointConfigured() throws Exception {
+	void testDetermineWmsUrlWithoutEndpointAndPlanStatusFestgestelltNoEndpointConfigured() throws Exception {
 		String wmsBaseUrl = "http://localhost:8080/xplan-wms/services/";
 		String wmsUrl = WmsUrlUtils.determineWmsUrl(FESTGESTELLT, mockConfigurationWithoutEndpoint(wmsBaseUrl));
 
-		assertThat(wmsUrl, is("http://localhost:8080/xplan-wms/services?"));
+		assertEquals("http://localhost:8080/xplan-wms/services?", wmsUrl);
 	}
 
 	@Test
-	public void testDetermineWmsUrlWithoutEndpointAndPlanStatusInAufstellungNoEndpointConfigured() throws Exception {
+	void testDetermineWmsUrlWithoutEndpointAndPlanStatusInAufstellungNoEndpointConfigured() throws Exception {
 		String wmsBaseUrl = "http://localhost:8080/xplan-wms/services/";
 		String wmsUrl = WmsUrlUtils.determineWmsUrl(IN_AUFSTELLUNG, mockConfigurationWithoutEndpoint(wmsBaseUrl));
 
-		assertThat(wmsUrl, is("http://localhost:8080/xplan-wms/services?"));
+		assertEquals("http://localhost:8080/xplan-wms/services?", wmsUrl);
 	}
 
 	@Test
-	public void testDetermineWmsUrlWithoutEndpointAndNullPlanStatusNoEndpointConfigured() throws Exception {
+	void testDetermineWmsUrlWithoutEndpointAndNullPlanStatusNoEndpointConfigured() throws Exception {
 		String wmsBaseUrl = "http://localhost:8080/xplan-wms/services/";
 		String wmsUrl = WmsUrlUtils.determineWmsUrl(null, mockConfigurationWithoutEndpoint(wmsBaseUrl));
 
-		assertThat(wmsUrl, is("http://localhost:8080/xplan-wms/services?"));
+		assertEquals("http://localhost:8080/xplan-wms/services?", wmsUrl);
 	}
 
 	@Test
-	public void testCreatePlanwerkWmsUrl() throws Exception {
+	void testCreatePlanwerkWmsUrl() throws Exception {
 		String wmsBaseUrl = "http://localhost:8080/xplan-wms/services/wms?";
 		String planwerkWmsUrl = WmsUrlUtils.createPlanwerkWmsUrl("PlanName10", mockConfiguration(wmsBaseUrl),
 				ARCHIVIERT);
 
-		assertThat(planwerkWmsUrl, is(
-				"http://localhost:8080/xplan-wms/services/planwerkwmsarchive/planname/PlanName10?request=GetCapabilities&service=WMS&version=1.3.0"));
+		assertEquals(
+				"http://localhost:8080/xplan-wms/services/planwerkwmsarchive/planname/PlanName10?request=GetCapabilities&service=WMS&version=1.3.0",
+				planwerkWmsUrl);
 	}
 
 	@Test
-	public void testCreatePlanwerkWmsUrlReplaceRequired() throws Exception {
+	void testCreatePlanwerkWmsUrlReplaceRequired() throws Exception {
 		String wmsBaseUrl = "http://localhost:8080/xplan-wms/services/wms?";
 		String planwerkWmsUrl = WmsUrlUtils.createPlanwerkWmsUrl("Plan Name 10 mit /", mockConfiguration(wmsBaseUrl),
 				FESTGESTELLT);
 
-		assertThat(planwerkWmsUrl, is(
-				"http://localhost:8080/xplan-wms/services/planwerkwms/planname/Plan Name 10 mit /?request=GetCapabilities&service=WMS&version=1.3.0"));
+		assertEquals(
+				"http://localhost:8080/xplan-wms/services/planwerkwms/planname/Plan Name 10 mit /?request=GetCapabilities&service=WMS&version=1.3.0",
+				planwerkWmsUrl);
 	}
 
 	@Test
-	public void testCreatePlanwerkWmsUrlReplaceRequiredWithServices() throws Exception {
+	void testCreatePlanwerkWmsUrlReplaceRequiredWithServices() throws Exception {
 		String wmsBaseUrl = "http://xplanservices.xplanbox.de/xplan-wms/services/wms?";
 		String planwerkWmsUrl = WmsUrlUtils.createPlanwerkWmsUrl("Plan Name 10 mit /", mockConfiguration(wmsBaseUrl),
 				IN_AUFSTELLUNG);
 
-		assertThat(planwerkWmsUrl, is(
-				"http://xplanservices.xplanbox.de/xplan-wms/services/planwerkwmspre/planname/Plan Name 10 mit /?request=GetCapabilities&service=WMS&version=1.3.0"));
+		assertEquals(
+				"http://xplanservices.xplanbox.de/xplan-wms/services/planwerkwmspre/planname/Plan Name 10 mit /?request=GetCapabilities&service=WMS&version=1.3.0",
+				planwerkWmsUrl);
 	}
 
 	private MapPreviewConfiguration mockConfigurationWithoutWmsEndpoint(String wmsUrl) {
diff --git a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/configuration/ManagerWebConfigurationRetrieverTest.java b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/configuration/ManagerWebConfigurationRetrieverTest.java
index b4a03644129b2c9bd51d9e894097adace422a1d4..94393c66b863a24be4ca21032c1b2d4a19752aa8 100644
--- a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/configuration/ManagerWebConfigurationRetrieverTest.java
+++ b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/configuration/ManagerWebConfigurationRetrieverTest.java
@@ -24,9 +24,6 @@ import de.latlon.xplan.manager.web.shared.ManagerWebConfiguration;
 import de.latlon.xplan.manager.web.shared.MapPreviewConfiguration;
 import de.latlon.xplan.manager.web.shared.RasterLayerConfiguration;
 import de.latlon.xplan.manager.web.shared.VectorLayerConfiguration;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -35,10 +32,13 @@ import java.io.InputStream;
 import java.nio.file.Files;
 import java.util.Properties;
 
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
 import static de.latlon.xplan.commons.configuration.SystemPropertyPropertiesLoader.CONFIG_SYSTEM_PROPERTY;
 import static org.apache.commons.io.IOUtils.copy;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 /**
  * Please note: This test uses static mocking of the <link>java.lang.System</link>-class,
@@ -47,70 +47,70 @@ import static org.hamcrest.MatcherAssert.assertThat;
  * @author <a href="mailto:erben@lat-lon.de">Alexander Erben</a>
  * @author <a href="mailto:wanhoff@lat-lon.de">Jeronimo Wanhoff</a>
  */
-public class ManagerWebConfigurationRetrieverTest {
+class ManagerWebConfigurationRetrieverTest {
 
 	private static final String PROPERTIES_NAME = "managerWebConfiguration.properties";
 
 	private static String oldProperty;
 
-	@BeforeClass
-	public static void copyPropertiesFileAndSetProxyConfigSystemVaraiable() throws IOException {
+	@BeforeAll
+	static void copyPropertiesFileAndSetProxyConfigSystemVaraiable() throws IOException {
 		File configDir = copyPropertiesFileToNewConfigDir();
 		oldProperty = System.getProperty(CONFIG_SYSTEM_PROPERTY);
 		System.setProperty(CONFIG_SYSTEM_PROPERTY, configDir.toString());
 	}
 
-	@AfterClass
-	public static void resetProxyConfigSystemProperty() {
+	@AfterAll
+	static void resetProxyConfigSystemProperty() {
 		if (oldProperty != null)
 			System.setProperty(CONFIG_SYSTEM_PROPERTY, oldProperty);
 	}
 
 	@Test
-	public void testSetupManagerWebConfigurationShouldReturnMatchingPropertiesFromSystemEnv() throws Exception {
+	void testSetupManagerWebConfigurationShouldReturnMatchingPropertiesFromSystemEnv() throws Exception {
 		ManagerWebConfiguration configuration = new ManagerWebConfigurationRetriever().setupManagerWebConfiguration();
 
 		Properties properties = loadPropertiesFromOriginalFile();
-		assertThat(configuration.isEditorActivated(), is(Boolean.valueOf(properties.getProperty("activateEditor"))));
+		assertEquals(Boolean.valueOf(properties.getProperty("activateEditor")), configuration.isEditorActivated());
 	}
 
 	@Test
-	public void testSetupMapPreviewConfigurationShouldReturnMatchingPropertiesFromSystemEnv() throws Exception {
+	void testSetupMapPreviewConfigurationShouldReturnMatchingPropertiesFromSystemEnv() throws Exception {
 		MapPreviewConfiguration configuration = new ManagerWebConfigurationRetriever().setupMapPreviewConfiguration();
 
 		Properties properties = loadPropertiesFromOriginalFile();
-		assertThat(configuration.getBasemapUrl(), is(properties.getProperty("basemapUrl")));
-		assertThat(configuration.getBasemapName(), is(properties.getProperty("basemapName")));
-		assertThat(configuration.getBasemapLayer(), is(properties.getProperty("basemapLayer")));
-		assertThat(configuration.getWmsUrl(), is(properties.getProperty("wmsUrl")));
+		assertEquals(properties.getProperty("basemapUrl"), configuration.getBasemapUrl());
+		assertEquals(properties.getProperty("basemapName"), configuration.getBasemapName());
+		assertEquals(properties.getProperty("basemapLayer"), configuration.getBasemapLayer());
+		assertEquals(properties.getProperty("wmsUrl"), configuration.getWmsUrl());
 	}
 
 	@Test
-	public void testSetupVectorLayerConfigurationShouldReturnMatchingPropertiesFromSystemEnv() throws Exception {
+	void testSetupVectorLayerConfigurationShouldReturnMatchingPropertiesFromSystemEnv() throws Exception {
 		VectorLayerConfiguration configuration = new ManagerWebConfigurationRetriever().setupMapPreviewConfiguration()
 			.getVectorLayerConfiguration();
 
 		Properties properties = loadPropertiesFromOriginalFile();
 
-		assertThat(configuration.getVectorWmsName(), is(properties.getProperty("vectorWmsName")));
-		assertThat(configuration.getBpVectorLayer(), is(properties.getProperty("bpVectorLayer")));
-		assertThat(configuration.getFpVectorLayer(), is(properties.getProperty("fpVectorLayer")));
-		assertThat(configuration.getLpVectorLayer(), is(properties.getProperty("lpVectorLayer")));
-		assertThat(configuration.getRpVectorLayer(), is(properties.getProperty("rpVectorLayer")));
+		assertEquals(properties.getProperty("vectorWmsName"), configuration.getVectorWmsName());
+		assertEquals(properties.getProperty("bpVectorLayer"), configuration.getBpVectorLayer());
+		assertEquals(properties.getProperty("fpVectorLayer"), configuration.getFpVectorLayer());
+		assertEquals(properties.getProperty("lpVectorLayer"), configuration.getLpVectorLayer());
+		assertEquals(properties.getProperty("rpVectorLayer"), configuration.getRpVectorLayer());
 	}
 
 	@Test
-	public void testSetupRasterLayerConfigurationShouldReturnMatchingPropertiesFromSystemEnv() throws Exception {
+	void testSetupRasterLayerConfigurationShouldReturnMatchingPropertiesFromSystemEnv() throws Exception {
 		RasterLayerConfiguration configuration = new ManagerWebConfigurationRetriever().setupMapPreviewConfiguration()
 			.getRasterLayerConfiguration();
 
 		Properties properties = loadPropertiesFromOriginalFile();
 
-		assertThat(configuration.getRasterWmsName(), is(properties.getProperty("rasterWmsName")));
-		assertThat(configuration.getBpRasterLayer(), is(properties.getProperty("bpRasterLayer")));
-		assertThat(configuration.getFpRasterLayer(), is(properties.getProperty("fpRasterLayer")));
-		assertThat(configuration.getLpRasterLayer(), is(properties.getProperty("lpRasterLayer")));
-		assertThat(configuration.getRpRasterLayer(), is(properties.getProperty("rpRasterLayer")));
+		assertEquals(properties.getProperty("rasterWmsName"), configuration.getRasterWmsName());
+		assertEquals(properties.getProperty("bpRasterLayer"), configuration.getBpRasterLayer());
+		assertEquals(properties.getProperty("fpRasterLayer"), configuration.getFpRasterLayer());
+		assertEquals(properties.getProperty("lpRasterLayer"), configuration.getLpRasterLayer());
+		assertEquals(properties.getProperty("rpRasterLayer"), configuration.getRpRasterLayer());
 	}
 
 	private static File copyPropertiesFileToNewConfigDir() throws IOException {
diff --git a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/configuration/ManagerWebConfigurationServiceImplTest.java b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/configuration/ManagerWebConfigurationServiceImplTest.java
index 141fcc032556042cf8fe4cb1c00fa378f5442f8b..3a91c576db668ee96db1facf9d2157ce6552a664 100644
--- a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/configuration/ManagerWebConfigurationServiceImplTest.java
+++ b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/configuration/ManagerWebConfigurationServiceImplTest.java
@@ -27,11 +27,10 @@ import de.latlon.xplan.manager.web.shared.MapPreviewConfiguration;
 import de.latlon.xplan.manager.web.shared.RasterLayerConfiguration;
 import de.latlon.xplan.manager.web.shared.VectorLayerConfiguration;
 import de.latlon.xplan.validator.web.shared.XPlanEnvelope;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
 
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -45,28 +44,28 @@ public class ManagerWebConfigurationServiceImplTest {
 
 	private static MapPreviewConfiguration mapPreviewConfiguration;
 
-	@BeforeClass
-	public static void setup() {
+	@BeforeAll
+	static void setup() {
 		managerWebConfiguration = createManagerWbConfig();
 		mapPreviewConfiguration = createMapPreviewConfig();
 	}
 
 	@Test
-	public void testGetManagerWebConfiguration() throws Exception {
+	void testGetManagerWebConfiguration() throws Exception {
 		ManagerWebConfigurationServiceImpl configurationService = retrieveConfigurationService(managerWebConfiguration);
 
 		ManagerWebConfiguration configuration = configurationService.getManagerWebConfiguration();
 
-		assertThat(configuration, is(managerWebConfiguration));
+		assertEquals(managerWebConfiguration, configuration);
 	}
 
 	@Test
-	public void testGetMapPreviewConfiguration() throws Exception {
+	void testGetMapPreviewConfiguration() throws Exception {
 		ManagerWebConfigurationServiceImpl configurationService = retrieveConfigurationService(mapPreviewConfiguration);
 
 		MapPreviewConfiguration configuration = configurationService.getMapPreviewConfiguration();
 
-		assertThat(configuration, is(mapPreviewConfiguration));
+		assertEquals(mapPreviewConfiguration, configuration);
 	}
 
 	protected ManagerWebConfigurationServiceImpl retrieveConfigurationService(ManagerWebConfiguration config)
diff --git a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/service/SecurityServiceImplTest.java b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/service/SecurityServiceImplTest.java
index 17cdb149530617566f8799e052c44d75d16924da..a2156072d761cd63421d303154cee0b7021130fb 100644
--- a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/service/SecurityServiceImplTest.java
+++ b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/service/SecurityServiceImplTest.java
@@ -22,7 +22,8 @@ package de.latlon.xplan.manager.web.server.service;
 
 import de.latlon.xplan.manager.web.server.service.security.AuthorizationManager;
 import de.latlon.xplan.manager.web.shared.AuthorizationInfo;
-import org.junit.Test;
+
+import org.junit.jupiter.api.Test;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
 
@@ -31,8 +32,8 @@ import java.util.Collections;
 import java.util.List;
 
 import static de.latlon.xplan.manager.web.spring.security.XPlanAuthorizationRole.ROLE_SUPERUSER;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
@@ -44,34 +45,34 @@ import static org.mockito.Mockito.when;
  * @author <a href="mailto:stenger@lat-lon.de">Dirk Stenger</a>
  * @version $Revision: $, $Date: $
  */
-public class SecurityServiceImplTest {
+class SecurityServiceImplTest {
 
 	@Test
-	public void testRetrieveAuthorizationInfo_WithEnabledSecurity() throws Exception {
+	void testRetrieveAuthorizationInfo_WithEnabledSecurity() throws Exception {
 		SecurityServiceImpl controllerWithEnabledSecurity = createSecurityController(true);
 		AuthorizationInfo authorizationInfo = controllerWithEnabledSecurity.retrieveAuthorizationInfo();
 		boolean isSuperUser = authorizationInfo.isSuperUser();
 
-		assertThat(isSuperUser, is(false));
+		assertFalse(isSuperUser);
 	}
 
 	@Test
-	public void testRetrieveAuthorizationInfo_WithEnabledSecurityShouldReturnSuperUser() throws Exception {
+	void testRetrieveAuthorizationInfo_WithEnabledSecurityShouldReturnSuperUser() throws Exception {
 		SecurityServiceImpl controllerWithEnabledSecurity = createSecurityController(true,
 				createAuthoritiesWithSuperUser());
 		AuthorizationInfo authorizationInfo = controllerWithEnabledSecurity.retrieveAuthorizationInfo();
 		boolean isSuperUser = authorizationInfo.isSuperUser();
 
-		assertThat(isSuperUser, is(true));
+		assertTrue(isSuperUser);
 	}
 
 	@Test
-	public void testRetrieveAuthorizationInfo_WithDisabledSecurityShouldReturnSuperUserPermissions() throws Exception {
+	void testRetrieveAuthorizationInfo_WithDisabledSecurityShouldReturnSuperUserPermissions() throws Exception {
 		AuthorizationManager securityManager = new AuthorizationManager(false);
 		SecurityServiceImpl controllerWithDisabledSecurity = new SecurityServiceImpl(securityManager);
 		AuthorizationInfo authorizationInfo = controllerWithDisabledSecurity.retrieveAuthorizationInfo();
 
-		assertThat(authorizationInfo.isSuperUser(), is(true));
+		assertTrue(authorizationInfo.isSuperUser());
 	}
 
 	private SecurityServiceImpl createSecurityController(boolean isSecurityEnabled) {
diff --git a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/service/rest/ManagerControllerTest.java b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/service/rest/ManagerControllerTest.java
index 11118f7f429b12247dff239df4fb20f8f4f01678..771ec8b3b2aeb0e347a3c3612248944e6b1b4268 100644
--- a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/service/rest/ManagerControllerTest.java
+++ b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/service/rest/ManagerControllerTest.java
@@ -20,44 +20,45 @@
  */
 package de.latlon.xplan.manager.web.server.service.rest;
 
-import de.latlon.xplan.manager.XPlanManager;
-import de.latlon.xplan.manager.web.shared.XPlan;
-import de.latlon.xplan.manager.web.spring.config.TestConfig;
-import de.latlon.xplan.manager.web.spring.config.XPlanManagerWebContextConfig;
-import de.latlon.xplanbox.core.gwt.commons.server.service.ReportProvider;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.mockito.ArgumentMatchers.isA;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import java.util.ArrayList;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.Mockito;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.test.context.ActiveProfiles;
 import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
 import org.springframework.test.context.web.WebAppConfiguration;
 import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 import org.springframework.web.context.WebApplicationContext;
 
+import de.latlon.xplan.manager.XPlanManager;
+import de.latlon.xplan.manager.web.shared.XPlan;
+import de.latlon.xplan.manager.web.spring.config.TestConfig;
+import de.latlon.xplan.manager.web.spring.config.XPlanManagerWebContextConfig;
+import de.latlon.xplanbox.core.gwt.commons.server.service.ReportProvider;
 import jakarta.servlet.http.HttpServletResponse;
-import java.util.ArrayList;
-
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.ArgumentMatchers.isA;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 
 /**
  * @author <a href="mailto:friebe@lat-lon.de">Torsten Friebe</a>
  */
-@RunWith(SpringJUnit4ClassRunner.class)
+@ExtendWith(SpringExtension.class)
 @ContextConfiguration(classes = { XPlanManagerWebContextConfig.class, TestConfig.class })
 @ActiveProfiles(profiles = { "test" })
 @WebAppConfiguration
-@Ignore
+@Disabled
 public class ManagerControllerTest {
 
 	private MockMvc mockMvc;
@@ -74,13 +75,13 @@ public class ManagerControllerTest {
 	@Autowired
 	private WebApplicationContext webApplicationContext;
 
-	@Before
+	@BeforeEach
 	public void setUp() {
 		mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
 	}
 
 	@Test
-	public void verifyThatManagerReturnList_WhenValidRequestIsSend() throws Exception {
+	void verifyThatManagerReturnList_WhenValidRequestIsSend() throws Exception {
 		doNothing().when(mockReportProvider)
 			.writeHtmlReport(isA(HttpServletResponse.class), isA(String.class), isA(String.class));
 		Mockito.when(mockManager.list()).thenReturn(new ArrayList<XPlan>());
diff --git a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/service/security/AuthorizationManagerTest.java b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/service/security/AuthorizationManagerTest.java
index 8166d284fe606e89a751df27b1f89c1f7825d763..2c0ababddb273eac15e60ad01f13c777195abd5c 100644
--- a/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/service/security/AuthorizationManagerTest.java
+++ b/xplan-manager/xplan-manager-web/src/test/java/de/latlon/xplan/manager/web/server/service/security/AuthorizationManagerTest.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%
@@ -23,7 +23,8 @@ package de.latlon.xplan.manager.web.server.service.security;
 import de.latlon.xplan.manager.web.server.service.SecurityServiceImpl;
 import de.latlon.xplan.manager.web.shared.AuthorizationInfo;
 import de.latlon.xplan.manager.web.shared.ConfigurationException;
-import org.junit.Test;
+
+import org.junit.jupiter.api.Test;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
 
@@ -32,8 +33,9 @@ import java.util.Collections;
 import java.util.List;
 
 import static de.latlon.xplan.manager.web.spring.security.XPlanAuthorizationRole.ROLE_SUPERUSER;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
@@ -43,50 +45,50 @@ import static org.mockito.Mockito.when;
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz</a>
  * @version $Revision: $, $Date: $
  */
-public class AuthorizationManagerTest {
+class AuthorizationManagerTest {
 
 	@Test
-	public void testCreateAuthorizationInfoFromAuthentication_WithEnabledSecurityShouldReturnSuperUser()
-			throws Exception {
+	void testCreateAuthorizationInfoFromAuthentication_WithEnabledSecurityShouldReturnSuperUser() throws Exception {
 		AuthorizationManager managerWithEnabledSecurity = createSecurityManager(true, createAuthoritiesWithSuperUser());
 		AuthorizationInfo authorizationInfo = managerWithEnabledSecurity.createAuthorizationInfoFromAuthentication();
 
-		assertThat(authorizationInfo.isSuperUser(), is(true));
+		assertTrue(authorizationInfo.isSuperUser());
 	}
 
 	@Test
-	public void testCreateAuthorizationInfoFromAuthentication_WithDisabledSecurityShouldReturnSuperUserPermissions()
+	void testCreateAuthorizationInfoFromAuthentication_WithDisabledSecurityShouldReturnSuperUserPermissions()
 			throws Exception {
 		AuthorizationManager managerWithEnabledSecurity = createSecurityManager(false);
 		AuthorizationInfo authorizationInfo = managerWithEnabledSecurity.createAuthorizationInfoFromAuthentication();
 
-		assertThat(authorizationInfo.isSuperUser(), is(false));
+		assertFalse(authorizationInfo.isSuperUser());
 	}
 
 	@Test
-	public void testIsSuperUser_WithEnabledSecurityFromNotSuperUser() throws Exception {
+	void testIsSuperUser_WithEnabledSecurityFromNotSuperUser() throws Exception {
 		AuthorizationManager managerWithEnabledSecurity = createSecurityManager(true);
-		assertThat(managerWithEnabledSecurity.isSuperUser(), is(false));
+		assertFalse(managerWithEnabledSecurity.isSuperUser());
 	}
 
 	@Test
-	public void testIsSuperUser_WithEnabledSecurityFromSuperUser() throws Exception {
+	void testIsSuperUser_WithEnabledSecurityFromSuperUser() throws Exception {
 		AuthorizationManager managerWithEnabledSecurity = createSecurityManager(true, createAuthoritiesWithSuperUser());
-		assertThat(managerWithEnabledSecurity.isSuperUser(), is(true));
+		assertTrue(managerWithEnabledSecurity.isSuperUser());
 	}
 
 	@Test
-	public void testIsSuperUser_WithDisabledSecurity() throws Exception {
+	void testIsSuperUser_WithDisabledSecurity() throws Exception {
 		AuthorizationManager managerWithEnabledSecurity = createSecurityManager(false);
-		assertThat(managerWithEnabledSecurity.isSuperUser(), is(true));
+		assertTrue(managerWithEnabledSecurity.isSuperUser());
 	}
 
-	@Test(expected = ConfigurationException.class)
-	public void testRetrieveAuthorizationInfoWithEnabledSecurityAndWithoutAuthenticationInstanceShouldThrowException()
+	@Test
+	void testRetrieveAuthorizationInfoWithEnabledSecurityAndWithoutAuthenticationInstanceShouldThrowException()
 			throws Exception {
 		AuthorizationManager securityManager = new AuthorizationManager(true);
 		SecurityServiceImpl controllerWithEnabledSecurity = new SecurityServiceImpl(securityManager);
-		controllerWithEnabledSecurity.retrieveAuthorizationInfo();
+
+		assertThrows(ConfigurationException.class, controllerWithEnabledSecurity::retrieveAuthorizationInfo);
 	}
 
 	private AuthorizationManager createSecurityManager(boolean isSecurityEnabled) {
diff --git a/xplan-tests/xplan-tests-selenium/.trivyignore b/xplan-tests/xplan-tests-selenium/.trivyignore
index 0b85d9274b3461651ef9232bab8974f1a3e1d917..a89d1b4a1aa6b42ed031bd1a456b6d2db778e3d3 100644
--- a/xplan-tests/xplan-tests-selenium/.trivyignore
+++ b/xplan-tests/xplan-tests-selenium/.trivyignore
@@ -1 +1 @@
-CVE-2017-1000487 # plexus-utils-1.5.8.jar is a dependency of spring-javaformat:0.0.39
+# no issue to ignore currently
\ No newline at end of file
diff --git a/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/XPlanboxConfig.java b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/TestConfig.java
similarity index 91%
rename from xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/XPlanboxConfig.java
rename to xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/TestConfig.java
index d69580316034251d7a02d7660c15cac26dc6e450..d139289f9729faccabe3925d8b2f9104b92b83be 100644
--- a/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/XPlanboxConfig.java
+++ b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/TestConfig.java
@@ -26,7 +26,7 @@ package de.latlon.xplanbox.tests;
  * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
  * @since 8.0
  */
-public record XPlanboxConfig(String dokumenteApiBaseUrl, String managerApiBaseUrl, String validatorApiBaseUrl,
+public record TestConfig(String dokumenteApiBaseUrl, String managerApiBaseUrl, String validatorApiBaseUrl,
 		String apiUsername, String apiPassword, String validatorWebBaseUrl, String validatorWebUsername,
 		String validatorWebPassword, RabbitConfig rabbitConfig) {
 
@@ -34,7 +34,7 @@ public record XPlanboxConfig(String dokumenteApiBaseUrl, String managerApiBaseUr
 			String publicFanoutQueueName) {
 	};
 
-	public static XPlanboxConfig getTestConfig() {
+	public static TestConfig getTestConfig() {
 		String dokumenteApiBaseUrl = getEnv("XPLAN_DOKUMENTEAPI_URL_PUBLIC",
 				"http://localhost:8092/xplan-dokumente-api");
 		String managerApiBaseUrl = getEnv("XPLAN_MANAGERAPI_URL_PUBLIC", "http://localhost:8086/xplan-manager-api");
@@ -57,7 +57,7 @@ public record XPlanboxConfig(String dokumenteApiBaseUrl, String managerApiBaseUr
 
 		RabbitConfig rabbitConfig = new RabbitConfig(rabbitHost, rabbitPort, rabbitUsername, rabbitPassword,
 				publicFanoutQueueName);
-		return new XPlanboxConfig(dokumenteApiBaseUrl, managerApiBaseUrl, validatorApiBaseUrl, apiUsername, apiPassword,
+		return new TestConfig(dokumenteApiBaseUrl, managerApiBaseUrl, validatorApiBaseUrl, apiUsername, apiPassword,
 				validatorWebBaseUrl, validatorWebUsername, validatorWebPassword, rabbitConfig);
 	}
 
diff --git a/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/dokumenteapi/TracingIT.java b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/dokumenteapi/TracingIT.java
index 7d1403aa70f2cf489581794b910241dd8e39adc9..619314288c0e3c839de045d3e96bb4ea9cec60ec 100644
--- a/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/dokumenteapi/TracingIT.java
+++ b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/dokumenteapi/TracingIT.java
@@ -23,7 +23,7 @@ package de.latlon.xplanbox.tests.dokumenteapi;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import de.latlon.xplanbox.tests.FeignUtils;
-import de.latlon.xplanbox.tests.XPlanboxConfig;
+import de.latlon.xplanbox.tests.TestConfig;
 import de.latlon.xplanbox.tests.dokumenteapi.DokumenteApi.TraceInfo;
 import feign.Feign;
 import feign.auth.BasicAuthRequestInterceptor;
@@ -38,7 +38,7 @@ class TracingIT {
 
 	@Test
 	void validateTraceIdAvailableInLog4jThreadContext() throws Exception {
-		XPlanboxConfig testConfig = XPlanboxConfig.getTestConfig();
+		TestConfig testConfig = TestConfig.getTestConfig();
 		BasicAuthRequestInterceptor interceptor = testConfig.apiUsername() != null
 				? new BasicAuthRequestInterceptor(testConfig.apiUsername(), testConfig.apiPassword()) : null;
 		DokumenteApi api = Feign.builder()
diff --git a/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/managerapi/TracingIT.java b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/managerapi/TracingIT.java
index 8fd19150fec949baa967f65770da20548b91b78e..36e30b8d1bfb6a1da8e050d23520fecc28d463a2 100644
--- a/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/managerapi/TracingIT.java
+++ b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/managerapi/TracingIT.java
@@ -23,7 +23,7 @@ package de.latlon.xplanbox.tests.managerapi;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import de.latlon.xplanbox.tests.FeignUtils;
-import de.latlon.xplanbox.tests.XPlanboxConfig;
+import de.latlon.xplanbox.tests.TestConfig;
 import de.latlon.xplanbox.tests.managerapi.ManagerApi.TraceInfo;
 import feign.Feign;
 import feign.auth.BasicAuthRequestInterceptor;
@@ -38,7 +38,7 @@ class TracingIT {
 
 	@Test
 	void validateTraceIdAvailableInLog4jThreadContext() throws Exception {
-		XPlanboxConfig testConfig = XPlanboxConfig.getTestConfig();
+		TestConfig testConfig = TestConfig.getTestConfig();
 		BasicAuthRequestInterceptor interceptor = testConfig.apiUsername() != null
 				? new BasicAuthRequestInterceptor(testConfig.apiUsername(), testConfig.apiPassword()) : null;
 		ManagerApi api = Feign.builder()
diff --git a/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/rabbit/AbstractRabbitITExecution.java b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/rabbit/AbstractRabbitITExecution.java
index 4dda1dfd18f9ed07068064ffef190583d619dfef..a5ac944037f95ae879b91842ca7aac21a83ffdf0 100644
--- a/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/rabbit/AbstractRabbitITExecution.java
+++ b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/rabbit/AbstractRabbitITExecution.java
@@ -17,7 +17,7 @@ import com.rabbitmq.client.Connection;
 import com.rabbitmq.client.ConnectionFactory;
 import com.rabbitmq.client.DeliverCallback;
 
-import de.latlon.xplanbox.tests.XPlanboxConfig.RabbitConfig;
+import de.latlon.xplanbox.tests.TestConfig.RabbitConfig;
 import feign.RequestTemplate;
 import feign.codec.EncodeException;
 import feign.codec.Encoder;
diff --git a/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/rabbit/manager/ManagerPublicEventsIT.java b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/rabbit/manager/ManagerPublicEventsIT.java
index a338f39027ccbbdcd781585ba59ac00d48cb44a5..26ed268a318013ee55dd6e25f729360aa02b5244 100644
--- a/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/rabbit/manager/ManagerPublicEventsIT.java
+++ b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/rabbit/manager/ManagerPublicEventsIT.java
@@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable;
 
 import de.latlon.xplanbox.tests.FeignUtils;
-import de.latlon.xplanbox.tests.XPlanboxConfig;
+import de.latlon.xplanbox.tests.TestConfig;
 import de.latlon.xplanbox.tests.rabbit.AbstractRabbitITExecution;
 import feign.Feign;
 import feign.jackson.JacksonDecoder;
@@ -22,7 +22,7 @@ import feign.jackson.JacksonDecoder;
 @DisabledIfEnvironmentVariable(named = "SKIP_RABBIT_TESTS", matches = "(1|true)")
 class ManagerPublicEventsIT extends AbstractRabbitITExecution {
 
-	private XPlanboxConfig testConfig = XPlanboxConfig.getTestConfig();
+	private TestConfig testConfig = TestConfig.getTestConfig();
 
 	@Test
 	void importAndVerifyPublicEvents() throws Exception {
diff --git a/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/rabbit/validator/ValidationPublicEventsIT.java b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/rabbit/validator/ValidationPublicEventsIT.java
index b8ae5cc7726a3e77586e59e8fc7f542b4db25aaa..ac243e44f7e968ae07b641845a2461fed8714e70 100644
--- a/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/rabbit/validator/ValidationPublicEventsIT.java
+++ b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/rabbit/validator/ValidationPublicEventsIT.java
@@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable;
 
 import de.latlon.xplanbox.tests.FeignUtils;
-import de.latlon.xplanbox.tests.XPlanboxConfig;
+import de.latlon.xplanbox.tests.TestConfig;
 import de.latlon.xplanbox.tests.rabbit.AbstractRabbitITExecution;
 import de.latlon.xplanbox.tests.validatorapi.ValidatorApi;
 import de.latlon.xplanbox.tests.validatorapi.ValidatorApi.StatusResponse;
@@ -25,7 +25,7 @@ import feign.jackson.JacksonDecoder;
 @DisabledIfEnvironmentVariable(named = "SKIP_RABBIT_TESTS", matches = "(1|true)")
 class ValidationPublicEventsIT extends AbstractRabbitITExecution {
 
-	private XPlanboxConfig testConfig = XPlanboxConfig.getTestConfig();
+	private TestConfig testConfig = TestConfig.getTestConfig();
 
 	@Test
 	void validateAndVerifyPublicEvents() throws Exception {
diff --git a/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/selenium/validatorweb/XPlanValidatorWebIT.java b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/selenium/validatorweb/XPlanValidatorWebIT.java
index 97f2557bdb34bc4b3745fd566f712feb48f78ee6..8d6cc3cd3b1c02488d6f248b5cac3823b3e71437 100644
--- a/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/selenium/validatorweb/XPlanValidatorWebIT.java
+++ b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/selenium/validatorweb/XPlanValidatorWebIT.java
@@ -30,7 +30,7 @@ import java.nio.file.Path;
 import java.util.HashMap;
 import java.util.Map;
 
-import de.latlon.xplanbox.tests.XPlanboxConfig;
+import de.latlon.xplanbox.tests.TestConfig;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.io.CleanupMode;
@@ -55,7 +55,7 @@ class XPlanValidatorWebIT {
 
 	@BeforeAll
 	static void readSystemProperties() {
-		XPlanboxConfig testConfig = XPlanboxConfig.getTestConfig();
+		TestConfig testConfig = TestConfig.getTestConfig();
 		String url = testConfig.validatorWebBaseUrl();
 		String username = testConfig.validatorWebUsername();
 		String password = testConfig.validatorWebPassword();
diff --git a/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/validatorapi/TracingIT.java b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/validatorapi/TracingIT.java
index ba6023684c5e59c8958913a7dd5481b4b77d6ac0..85503e9004322e7abe7588d411e3f41b4ac1b59a 100644
--- a/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/validatorapi/TracingIT.java
+++ b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/validatorapi/TracingIT.java
@@ -23,7 +23,7 @@ package de.latlon.xplanbox.tests.validatorapi;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import de.latlon.xplanbox.tests.FeignUtils;
-import de.latlon.xplanbox.tests.XPlanboxConfig;
+import de.latlon.xplanbox.tests.TestConfig;
 import de.latlon.xplanbox.tests.validatorapi.ValidatorApi.TraceInfo;
 import feign.Feign;
 import feign.auth.BasicAuthRequestInterceptor;
@@ -38,7 +38,7 @@ class TracingIT {
 
 	@Test
 	void validateTraceIdAvailableInLog4jThreadContext() throws Exception {
-		XPlanboxConfig testConfig = XPlanboxConfig.getTestConfig();
+		TestConfig testConfig = TestConfig.getTestConfig();
 		BasicAuthRequestInterceptor interceptor = testConfig.apiUsername() != null
 				? new BasicAuthRequestInterceptor(testConfig.apiUsername(), testConfig.apiPassword()) : null;
 		ValidatorApi validatorApi = Feign.builder()
diff --git a/xplan-tests/xplan-tests-soapui/.trivyignore b/xplan-tests/xplan-tests-soapui/.trivyignore
index f98bd19cd7528763717ad534dc283727f826824e..8546d21dbc78370a01e45fabb055e64ab1e55874 100644
--- a/xplan-tests/xplan-tests-soapui/.trivyignore
+++ b/xplan-tests/xplan-tests-soapui/.trivyignore
@@ -1,6 +1,4 @@
 CVE-2023-26119 # htmlunit-2.7.jar is a dependency of soapui-maven-plugin 5.7.2
 
-CVE-2017-1000487 # plexus-utils-1.5.8.jar is a dependency of spring-javaformat:0.0.39
-
 CVE-2018-8088 # slf4j-ext-1.7.22.jar seems to be a dependency of soapui-maven-plugin 5.7.2
 
diff --git a/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-manager-api-soapui-project.xml b/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-manager-api-soapui-project.xml
index 4e8bd742b63bd56ad7a52f79890eb7b5a82fd4ac..22f540f6614fd59d144f49f0834b77ad5258a723 100644
--- a/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-manager-api-soapui-project.xml
+++ b/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-manager-api-soapui-project.xml
@@ -209,7 +209,7 @@ Import the plan</con:description>
         </con:representation>
         <con:representation type="FAULT">
           <con:mediaType>application/json</con:mediaType>
-          <con:status>400 406 415</con:status>
+          <con:status>400 406 415 422</con:status>
           <con:params/>
           <con:element xmlns:plan="http://localhost/xplan-manager-api/xmanager/api/v1/plan">plan:Fault</con:element>
         </con:representation>
@@ -239,7 +239,7 @@ Import the plan</con:description>
         </con:representation>
         <con:representation type="FAULT">
           <con:mediaType>application/vnd.xplanbox.api+json</con:mediaType>
-          <con:status>400 406</con:status>
+          <con:status>400 406 500</con:status>
           <con:params/>
           <con:element xmlns:plan="http://localhost/xplan-manager-api/xmanager/api/v1/plan">plan:Fault</con:element>
         </con:representation>
@@ -383,6 +383,18 @@ Get plan identified by the given planName</con:description>
           <con:params/>
           <con:element>data</con:element>
         </con:representation>
+        <con:representation type="RESPONSE">
+          <con:mediaType xsi:nil="true"/>
+          <con:status>0</con:status>
+          <con:params/>
+          <con:element>data</con:element>
+        </con:representation>
+        <con:representation type="RESPONSE">
+          <con:mediaType xsi:nil="true"/>
+          <con:status>0</con:status>
+          <con:params/>
+          <con:element>data</con:element>
+        </con:representation>
         <con:request name="Request 1" id="1136be8a-8ab3-4338-b970-bdc7d6136107" mediaType="application/json">
           <con:settings/>
           <con:endpoint>${#Project#baseUrlManagerApi}/xplan-manager-api/xmanager/api/v1</con:endpoint>
@@ -2198,6 +2210,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="9c116865-1397-455f-9261-af3b7d0f17cb" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="9c116865-1397-455f-9261-af3b7d0f17cb" name="link planwerk">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwmspre/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -2370,6 +2402,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="031ac702-0dd7-4ee6-b0a2-af9b263d6af3" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/vnd.xplanbox.api+json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="201ce67b-392b-4c79-b660-bcac1981f760" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -2484,6 +2536,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="661feb7b-2379-46aa-a994-f7034df08aaf" name="link self">
+              <con:configuration>
+                <path>$[0].links[?(@.rel == 'self' &amp;&amp; @.type == 'application/vnd.xplanbox.api.v2+json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="76746657-6e7d-4550-a451-403b37a970e0" name="link planwerkwms">
+              <con:configuration>
+                <path>$[0].links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -2655,6 +2727,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="1c5514d8-72bf-4781-87eb-227faffc6315" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/vnd.xplanbox.api.v1+json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="1c5514d8-72bf-4781-87eb-227faffc6315" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwmspre/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -2810,6 +2902,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="abf825ba-2931-4771-aec7-ce9676321275" name="link self">
+              <con:configuration>
+                <path>$[0].links[?(@.rel == 'self' &amp;&amp; @.type == 'application/vnd.xplanbox.api.v2+json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="abf825ba-2931-4771-aec7-ce9676321275" name="link planwerkwms">
+              <con:configuration>
+                <path>$[0].links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -3028,6 +3140,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="d66e6bfc-96cf-4ab7-9fd1-b3fc16a50325" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="d66e6bfc-96cf-4ab7-9fd1-b3fc16a50325" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -3133,6 +3265,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="e1a6634c-04ec-4828-b6b6-abfbdd1868ea" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/vnd.xplanbox.api+json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="e1a6634c-04ec-4828-b6b6-abfbdd1868ea" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwmspre/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -3307,6 +3459,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="af4ba2fe-caa2-4617-9f25-5523e3406462" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/vnd.xplanbox.api+json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="af4ba2fe-caa2-4617-9f25-5523e3406462" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -3634,6 +3806,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="6ea52527-2a67-45db-be8c-5c5db7cd4e2e" name="link self">
+              <con:configuration>
+                <path>$[0].links[?(@.rel == 'self' &amp;&amp; @.type == 'application/vnd.xplanbox.api.v2+json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="6ea52527-2a67-45db-be8c-5c5db7cd4e2e" name="link planwerkwms">
+              <con:configuration>
+                <path>$[0].links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -3744,6 +3936,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="766fb9a5-8bf7-472d-9365-6259e042b62f" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="766fb9a5-8bf7-472d-9365-6259e042b62f" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwmsarchive/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -3904,6 +4116,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="4823fa45-b923-4621-8a26-1cf2777f11d3" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="4823fa45-b923-4621-8a26-1cf2777f11d3" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwmsarchive/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -4014,6 +4246,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="c62350b9-98d9-4816-bd38-931acba8f34f" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="c62350b9-98d9-4816-bd38-931acba8f34f" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -4133,6 +4385,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="9153eaa6-ceea-42c0-a549-1c2eb912c705" name="link self">
+              <con:configuration>
+                <path>$[0].links[?(@.rel == 'self' &amp;&amp; @.type == 'application/vnd.xplanbox.api.v2+json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="9153eaa6-ceea-42c0-a549-1c2eb912c705" name="link planwerkwms">
+              <con:configuration>
+                <path>$[0].links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -4238,6 +4510,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="11f6bdb1-6e35-43b9-aaab-19f19bb9fce5" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="11f6bdb1-6e35-43b9-aaab-19f19bb9fce5" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -4350,6 +4642,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="529a68b9-7584-4c7c-85b3-7a64cef98107" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="529a68b9-7584-4c7c-85b3-7a64cef98107" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwmsarchive/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -4460,6 +4772,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="4f6d7a6b-5d7f-4341-8e62-26b8afbb0db7" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="4f6d7a6b-5d7f-4341-8e62-26b8afbb0db7" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -4570,6 +4902,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="81108919-8476-43a4-ac18-159e41f544e6" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="81108919-8476-43a4-ac18-159e41f544e6" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -4680,6 +5032,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="dfb288e8-2f67-4e67-b6f9-e513800fd317" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="dfb288e8-2f67-4e67-b6f9-e513800fd317" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -4781,6 +5153,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="9406a6f9-31e9-4e4d-b5bd-fe9114559d7e" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="9406a6f9-31e9-4e4d-b5bd-fe9114559d7e" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -5095,6 +5487,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="bf38df3f-26d1-46dd-a36e-dd867f43d213" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="bf38df3f-26d1-46dd-a36e-dd867f43d213" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -5200,6 +5612,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="0c1db00d-5c3a-4c39-8115-1461a362cdf7" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="0c1db00d-5c3a-4c39-8115-1461a362cdf7" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwmspre/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -5302,6 +5734,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="0d992970-3dec-42a4-8eab-e40496494b23" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="0d992970-3dec-42a4-8eab-e40496494b23" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwmspre/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -5415,6 +5867,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="5216eb6b-85a7-4122-9389-62bf3bedfcdd" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="5216eb6b-85a7-4122-9389-62bf3bedfcdd" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -5536,6 +6008,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="76366bea-4f40-4e20-b8dd-9d1a5d4293c1" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="76366bea-4f40-4e20-b8dd-9d1a5d4293c1" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwmspre/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -6048,6 +6540,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="16562d56-38a6-4e35-95e1-fdc39fe008fa" name="link self">
+              <con:configuration>
+                <path>$[0].links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="16562d56-38a6-4e35-95e1-fdc39fe008fa" name="link planwerkwms">
+              <con:configuration>
+                <path>$[0].links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -6062,10 +6574,10 @@ assert actualHeader != null</scriptText>
           </con:restRequest>
         </con:config>
       </con:testStep>
-      <con:testStep type="restrequest" name="GET XX X.X pN invalidPlanNameExpectError404" id="76c1fe6b-4860-49d0-ab41-c486b3fd3508" disabled="true">
+      <con:testStep type="restrequest" name="GET XX X.X pN invalidPlanName" id="76c1fe6b-4860-49d0-ab41-c486b3fd3508">
         <con:settings/>
         <con:config service="XPlanManagerAPI" resourcePath="/plan/name/{planName}" methodName="getByName" xsi:type="con:RestRequestStep" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-          <con:restRequest name="GET XX X.X pN invalidPlanNameExpectError404" id="25618c12-48a4-4be8-8a88-5826c061b358" mediaType="application/json">
+          <con:restRequest name="GET XX X.X pN invalidPlanName" id="25618c12-48a4-4be8-8a88-5826c061b358" mediaType="application/json">
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;entry key="Accept" value="application/json" xmlns="http://eviware.com/soapui/config"/></con:setting>
             </con:settings>
@@ -6074,7 +6586,16 @@ assert actualHeader != null</scriptText>
             <con:originalUri>http://localhost/xplan-manager-api/xmanager/api/v1/plan/name/</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7af8bd28-cbdf-429d-adba-8fae4efb7ae5" name="Valid HTTP Status Codes">
               <con:configuration>
-                <codes>404</codes>
+                <codes>200</codes>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath Match" id="15d1a948-f88c-4b8d-aa7e-4ee56ee9bc68" name="empty list">
+              <con:configuration>
+                <path>$</path>
+                <content>[]</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
             <con:credentials>
@@ -6194,6 +6715,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="4a57e07a-a8c7-4341-92cd-ce53cb3a5cc2" name="link self">
+              <con:configuration>
+                <path>$[0].links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="4a57e07a-a8c7-4341-92cd-ce53cb3a5cc2" name="link planwerkwms">
+              <con:configuration>
+                <path>$[0].links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -6262,22 +6803,42 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
-            <con:assertion type="JsonPath Match" id="4e49f759-7fd9-4f6c-951e-09cd193baaf4" name="gemeinden.gemeindeName">
+            <con:assertion type="JsonPath Match" id="4e49f759-7fd9-4f6c-951e-09cd193baaf4" name="gemeinden.gemeindeName">
+              <con:configuration>
+                <path>$[0].xplanModelData.gemeinden[0].gemeindeName</path>
+                <content>Hamburg</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath Match" id="4e49f759-7fd9-4f6c-951e-09cd193baaf4" name="gemeinden.ortsteilName">
+              <con:configuration>
+                <path>$[0].xplanModelData.gemeinden[0].ortsteilName</path>
+                <content>Bezirk Eimsbüttel Ortsteil 320</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="a882fdf6-8bd3-4a7e-af73-632f788811b6" name="link self">
               <con:configuration>
-                <path>$[0].xplanModelData.gemeinden[0].gemeindeName</path>
-                <content>Hamburg</content>
+                <path>$[0].links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
                 <allowWildcards>false</allowWildcards>
                 <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
                 <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
               </con:configuration>
             </con:assertion>
-            <con:assertion type="JsonPath Match" id="4e49f759-7fd9-4f6c-951e-09cd193baaf4" name="gemeinden.ortsteilName">
+            <con:assertion type="JsonPath RegEx Match" id="a882fdf6-8bd3-4a7e-af73-632f788811b6" name="link planwerkwms">
               <con:configuration>
-                <path>$[0].xplanModelData.gemeinden[0].ortsteilName</path>
-                <content>Bezirk Eimsbüttel Ortsteil 320</content>
+                <path>$[0].links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
                 <allowWildcards>false</allowWildcards>
                 <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
                 <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
               </con:configuration>
             </con:assertion>
             <con:credentials>
@@ -6357,6 +6918,26 @@ assert actualHeader != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="6d6a0d2d-70e8-4ede-9ebe-9d543ad40610" name="link self">
+              <con:configuration>
+                <path>$[0].links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="6d6a0d2d-70e8-4ede-9ebe-9d543ad40610" name="link planwerkwms">
+              <con:configuration>
+                <path>$[0].links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -6377,7 +6958,7 @@ assert actualHeader != null</scriptText>
       <con:testStep type="restrequest" name="GET BP 5.4 pI,pN invalidPlanNameExpectError400" id="60bb9823-bfc2-4bae-bdce-a8fda7507667">
         <con:settings/>
         <con:config service="XPlanManagerAPI" resourcePath="/plans" methodName="invalidPlanIdAndPlanName" xsi:type="con:RestRequestStep" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-          <con:restRequest name="GET BP 5.4 pI,pN invalidPlanNameExpectError" id="ba7c71b2-c264-4a61-b0b0-1146f2594e7e" mediaType="application/json">
+          <con:restRequest name="GET BP 5.4 pI,pN invalidPlanNameExpectError400" id="ba7c71b2-c264-4a61-b0b0-1146f2594e7e" mediaType="application/json">
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
@@ -17491,6 +18072,26 @@ if (documentUrl != "null"){
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="8b3c24e4-9eb8-4676-9a4e-57a4c6f3747b" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="8b3c24e4-9eb8-4676-9a4e-57a4c6f3747b" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -17507,10 +18108,10 @@ if (documentUrl != "null"){
           </con:restRequest>
         </con:config>
       </con:testStep>
-      <con:testStep type="restrequest" name="GET BP 4.1 pI CurrentStatusAcceptApplication/XML" id="cb1f57b5-6c9c-4bfb-8f7f-3fa0c21cd020">
+      <con:testStep type="restrequest" name="GET BP 4.1 pI currentStatusAcceptApplication/XML" id="cb1f57b5-6c9c-4bfb-8f7f-3fa0c21cd020">
         <con:settings/>
         <con:config service="XPlanManagerAPI" resourcePath="/plan/{planId}" methodName="getById" xsi:type="con:RestRequestStep" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-          <con:restRequest name="GET BP 4.1 pI CurrentStatusAcceptApplication/XML" id="f9bcc4d9-872e-472c-96b8-27484a6e67a3" mediaType="application/json">
+          <con:restRequest name="GET BP 4.1 pI currentStatusAcceptApplication/XML" id="f9bcc4d9-872e-472c-96b8-27484a6e67a3" mediaType="application/json">
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;entry key="Accept" value="application/xml" xmlns="http://eviware.com/soapui/config"/></con:setting>
             </con:settings>
@@ -17576,6 +18177,24 @@ if (documentUrl != "null"){
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="XPath Match" id="319a5f6f-d339-465f-9f40-a0a0ec856134" name="link self">
+              <con:configuration>
+                <path>contains(/planInfo/links[rel='SELF']/href, '/api/v1/plan/')</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="XPath Match" id="319a5f6f-d339-465f-9f40-a0a0ec856134" name="link planwerkwms">
+              <con:configuration>
+                <path>contains(/planInfo/links[rel='PLANWERKWMS']/href, '/services/planwerkwms/planname/')</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -17592,10 +18211,10 @@ if (documentUrl != "null"){
           </con:restRequest>
         </con:config>
       </con:testStep>
-      <con:testStep type="restrequest" name="GET BP 4.1 pI CurrentStatusAcceptApplication/ZIP" id="af3d894d-aede-435f-bcf3-83978eadc75e">
+      <con:testStep type="restrequest" name="GET BP 4.1 pI currentStatusAcceptApplication/ZIP" id="af3d894d-aede-435f-bcf3-83978eadc75e">
         <con:settings/>
         <con:config service="XPlanManagerAPI" resourcePath="/plan/{planId}" methodName="getById" xsi:type="con:RestRequestStep" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-          <con:restRequest name="GET BP 4.1 pI CurrentStatusAcceptApplication/ZIP" id="f9bcc4d9-872e-472c-96b8-27484a6e67a3" mediaType="application/json">
+          <con:restRequest name="GET BP 4.1 pI currentStatusAcceptApplication/ZIP" id="f9bcc4d9-872e-472c-96b8-27484a6e67a3" mediaType="application/json">
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;entry key="Accept" value="application/zip" xmlns="http://eviware.com/soapui/config"/></con:setting>
             </con:settings>
@@ -17740,6 +18359,26 @@ assert expectedHeader == actualHeader</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="5d67e227-dc12-474d-887c-a831ad62b6bd" name="link self">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/api/v1/plan/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
+            <con:assertion type="JsonPath RegEx Match" id="5d67e227-dc12-474d-887c-a831ad62b6bd" name="link planwerkwms">
+              <con:configuration>
+                <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+                <regEx>^.*/services/planwerkwmspre/planname/.*$</regEx>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -19662,6 +20301,121 @@ assert expectedHeader == actualHeader</scriptText>
           <con:parameters/>
         </con:config>
       </con:testStep>
+      <con:testStep type="httprequest" name="POST BP 6.0 xF,sS,sF,sG,sL,iI,pS importPlanFailingValidationExpectError400" id="5aa4570f-424d-41d2-b774-f3639251f4c8">
+        <con:settings/>
+        <con:config method="POST" xsi:type="con:HttpRequest" id="fb82fa77-b86e-45f2-8c0f-866cb490b0d1" name="POST BP 6.0 xF,sS,sF,sG,sL,iI,pS importPlanFailingValidationExpectError400" postQueryString="false" mediaType="application/octet-stream" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+          <con:settings>
+            <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment xmlns:con="http://eviware.com/soapui/config">
+  &lt;con:entry key="Accept" value="application/json"/>
+  &lt;con:entry key="X-Filename" value="soapui-test"/>
+&lt;/xml-fragment></con:setting>
+          </con:settings>
+          <con:endpoint>${#Project#baseUrlManagerApi}/xplan-manager-api/xmanager/api/v1/plan</con:endpoint>
+          <con:request/>
+          <con:assertion type="Valid HTTP Status Codes" id="de44e7cd-c4f2-4f55-90d8-367bea84ef1e" name="Valid HTTP Status Codes">
+            <con:configuration>
+              <codes>400</codes>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="730f17f4-56c5-4641-965d-511ec286741e" name="externalReferencesResult.name">
+            <con:configuration>
+              <path>$.externalReferencesResult[?(@.name == "BPlan004_6-0.png")].name</path>
+              <content>[BPlan004_6-0.png]</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="730f17f4-56c5-4641-965d-511ec286741e" name="externalReferencesResult.status">
+            <con:configuration>
+              <path>$.externalReferencesResult[?(@.name == "BPlan004_6-0.png")].status</path>
+              <content>[AVAILABLE]</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="621da0fd-5c0d-4e54-bf8c-2e0a0f42872a" name="rasterEvaluationResults.name">
+            <con:configuration>
+              <path>$.rasterEvaluationResults[?(@.name == "BPlan004_6-0.png")].name</path>
+              <content>[BPlan004_6-0.png]</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="621da0fd-5c0d-4e54-bf8c-2e0a0f42872a" name="rasterEvaluationResults.crsStatus">
+            <con:configuration>
+              <path>$.rasterEvaluationResults[?(@.name == "BPlan004_6-0.png")].crsStatus</path>
+              <content>[MISSING]</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="621da0fd-5c0d-4e54-bf8c-2e0a0f42872a" name="rasterEvaluationResults.imageFormatStatus">
+            <con:configuration>
+              <path>$.rasterEvaluationResults[?(@.name == "BPlan004_6-0.png")].imageFormatStatus</path>
+              <content>[SUPPORTED]</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:credentials>
+            <con:username>${#Project#username}</con:username>
+            <con:password>${#Project#password}</con:password>
+            <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
+            <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
+            <con:preemptive>true</con:preemptive>
+            <con:authType>Preemptive</con:authType>
+          </con:credentials>
+          <con:attachment>
+            <con:name>FP_6.0.2.zip</con:name>
+            <con:contentType>application/octet-stream</con:contentType>
+            <con:contentId>BPlan004_6-0.zip</con:contentId>
+            <con:url>${projectDir}/xplan-manager-api/plans/BPlan004_6-0_ValidationError.zip</con:url>
+            <con:id>e65ee7a4-20dd-461e-a899-ae69d9a90731</con:id>
+          </con:attachment>
+          <con:jmsConfig JMSDeliveryMode="PERSISTENT"/>
+          <con:jmsPropertyConfig/>
+          <con:parameters>
+            <con:parameter>
+              <con:name>skipSemantisch</con:name>
+              <con:value>true</con:value>
+              <con:style>QUERY</con:style>
+            </con:parameter>
+            <con:parameter>
+              <con:name>skipFlaechenschluss</con:name>
+              <con:value>true</con:value>
+              <con:style>QUERY</con:style>
+            </con:parameter>
+            <con:parameter>
+              <con:name>skipGeltungsbereich</con:name>
+              <con:value>true</con:value>
+              <con:style>QUERY</con:style>
+            </con:parameter>
+            <con:parameter>
+              <con:name>skipLaufrichtung</con:name>
+              <con:value>true</con:value>
+              <con:style>QUERY</con:style>
+            </con:parameter>
+            <con:parameter required="false" disableUrlEncoding="false">
+              <con:name>internalId</con:name>
+              <con:value>soapui-test-id</con:value>
+              <con:style>QUERY</con:style>
+              <con:type xmlns:xs="http://www.w3.org/2001/XMLSchema">xs:string</con:type>
+              <con:default/>
+              <con:description xsi:nil="true"/>
+            </con:parameter>
+            <con:parameter>
+              <con:name>planStatus</con:name>
+              <con:value>FESTGESTELLT</con:value>
+              <con:style>QUERY</con:style>
+            </con:parameter>
+          </con:parameters>
+        </con:config>
+      </con:testStep>
       <con:testStep type="httprequest" name="POST BP 6.0 xF,sS,sF,sG,sL,iI,pS importPlanWithMissingPNGExpectError400" id="cfe0eed5-d8f1-44ee-b4a6-2918697df01b">
         <con:settings/>
         <con:config method="POST" xsi:type="con:HttpRequest" id="fb82fa77-b86e-45f2-8c0f-866cb490b0d1" name="POST BP 6.0 xF,sS,sF,sG,sL,iI,pS importPlanWithMissingPNGExpectError400" postQueryString="false" mediaType="application/octet-stream" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
@@ -20211,6 +20965,15 @@ assert expectedHeader == actualHeader</scriptText>
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
+          <con:assertion type="JsonPath Match" id="338faceb-131f-43eb-bf38-2bf035ec149f" name="path /plan response 200 description">
+            <con:configuration>
+              <path>$.paths./plan.post.responses.200.description</path>
+              <content>ImportReceipt with uuid of the import</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -20776,33 +21539,6 @@ assert json.version != null</scriptText>
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="129ac743-0353-43ba-93a5-97580a06afee" name="errorMsgExists">
-            <con:configuration>
-              <path>$.errorMsg</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="320f668b-21ff-4589-a944-cfbd07931e2a" name="importedPlanIdsExists">
-            <con:configuration>
-              <path>$.importedPlanIds</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="493b851d-f4cf-4289-90b8-3cb49d482b72" name="linksExists">
-            <con:configuration>
-              <path>$.links</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -20861,40 +21597,72 @@ if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "IMPORT_FINISHED" ){
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="129ac743-0353-43ba-93a5-97580a06afee" name="errorMsgExists">
+          <con:assertion type="JsonPath Existence Match" id="320f668b-21ff-4589-a944-cfbd07931e2a" name="importedPlanIdsExists">
             <con:configuration>
-              <path>$.errorMsg</path>
+              <path>$.importedPlanIds</path>
               <content>true</content>
               <allowWildcards>false</allowWildcards>
               <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="320f668b-21ff-4589-a944-cfbd07931e2a" name="importedPlanIdsExists">
+          <con:assertion type="JsonPath Existence Match" id="493b851d-f4cf-4289-90b8-3cb49d482b72" name="linksExists">
             <con:configuration>
-              <path>$.importedPlanIds</path>
+              <path>$.links</path>
               <content>true</content>
               <allowWildcards>false</allowWildcards>
               <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="493b851d-f4cf-4289-90b8-3cb49d482b72" name="linksExists">
+          <con:assertion type="JsonPath RegEx Match" id="af671b26-7707-43bd-a3c9-5f085cd3dff5" name="schema report">
             <con:configuration>
-              <path>$.links</path>
+              <path>$.links[?(@.rel == 'report' &amp;&amp; @.type == 'application/json')].schema</path>
               <content>true</content>
               <allowWildcards>false</allowWildcards>
               <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
               <ignoreComments>false</ignoreComments>
+              <regEx>^.*/api/v2#/components/schemas/ValidationReport.*$</regEx>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="a9ed262c-75d6-4a67-ad13-5b40ce1eb9ac" name="hrefExists">
+          <con:assertion type="JsonPath RegEx Match" id="af671b26-7707-43bd-a3c9-5f085cd3dff5" name="schema planinfo">
             <con:configuration>
-              <path>$.links[0].href</path>
+              <path>$.links[?(@.rel == 'planinfo' &amp;&amp; @.type == 'application/json')].schema</path>
+              <content>false</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+              <regEx>/api/v2#/components/schemas/PlanInfo</regEx>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath RegEx Match" id="d9eefe15-72b1-4ead-a022-0839c587fcda" name="href report json">
+            <con:configuration>
+              <path>$.links[?(@.rel == 'report' &amp;&amp; @.type == 'application/json')].href</path>
+              <content>true</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+              <regEx>^.*report.json.*$</regEx>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath RegEx Match" id="d9eefe15-72b1-4ead-a022-0839c587fcda" name="href report pdf">
+            <con:configuration>
+              <path>$.links[?(@.rel == 'report' &amp;&amp; @.type == 'application/pdf')].href</path>
+              <content>true</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+              <regEx>^.*report.pdf.*$</regEx>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath RegEx Match" id="d9eefe15-72b1-4ead-a022-0839c587fcda" name="href planinfo">
+            <con:configuration>
+              <path>$.links[?(@.rel == 'planinfo' &amp;&amp; @.type == 'application/json')].href</path>
               <content>true</content>
               <allowWildcards>false</allowWildcards>
               <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
               <ignoreComments>false</ignoreComments>
+              <regEx>^.*/api/v2/plan/.*$</regEx>
             </con:configuration>
           </con:assertion>
           <con:credentials>
@@ -20980,45 +21748,18 @@ if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "IMPORT_FINISHED" ){
         <con:settings/>
         <con:config method="GET" xsi:type="con:HttpRequest" id="d219264b-19a2-4e32-bda8-d1d431e563e9" name="GET BP 6.0.2 sU pollStatusMismatchingTypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
           <con:settings>
-            <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;entry key="Accept" value="application/json" xmlns="http://eviware.com/soapui/config"/></con:setting>
-          </con:settings>
-          <con:endpoint>${#TestSuite#hrefStatusMismatchingTypes}</con:endpoint>
-          <con:request/>
-          <con:assertion type="Valid HTTP Status Codes" id="706a255f-d031-4dfe-b078-d7098c7d2b4a" name="Valid HTTP Status Codes">
-            <con:configuration>
-              <codes>200</codes>
-            </con:configuration>
-          </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="8c1a42b6-d7c1-4c77-91c6-b7d4c3fc4530" name="statusExists">
-            <con:configuration>
-              <path>$.status</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="129ac743-0353-43ba-93a5-97580a06afee" name="errorMsgExists">
-            <con:configuration>
-              <path>$.errorMsg</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="320f668b-21ff-4589-a944-cfbd07931e2a" name="importedPlanIdsExists">
+            <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;entry key="Accept" value="application/json" xmlns="http://eviware.com/soapui/config"/></con:setting>
+          </con:settings>
+          <con:endpoint>${#TestSuite#hrefStatusMismatchingTypes}</con:endpoint>
+          <con:request/>
+          <con:assertion type="Valid HTTP Status Codes" id="706a255f-d031-4dfe-b078-d7098c7d2b4a" name="Valid HTTP Status Codes">
             <con:configuration>
-              <path>$.importedPlanIds</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
+              <codes>200</codes>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="493b851d-f4cf-4289-90b8-3cb49d482b72" name="linksExists">
+          <con:assertion type="JsonPath Existence Match" id="8c1a42b6-d7c1-4c77-91c6-b7d4c3fc4530" name="statusExists">
             <con:configuration>
-              <path>$.links</path>
+              <path>$.status</path>
               <content>true</content>
               <allowWildcards>false</allowWildcards>
               <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
@@ -21092,24 +21833,6 @@ if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "VALIDATION_FAILED" ){
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Match" id="d7f0823c-c0f0-46b2-8c85-26b6e828a833" name="importedPlanIds">
-            <con:configuration>
-              <path>$.importedPlanIds</path>
-              <content>null</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
-          <con:assertion type="JsonPath Match" id="69eedd5e-af1f-4496-9645-974bd7cf8191" name="links">
-            <con:configuration>
-              <path>$.links</path>
-              <content>null</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -21145,33 +21868,6 @@ if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "VALIDATION_FAILED" ){
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="129ac743-0353-43ba-93a5-97580a06afee" name="errorMsgExists">
-            <con:configuration>
-              <path>$.errorMsg</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="320f668b-21ff-4589-a944-cfbd07931e2a" name="importedPlanIdsExists">
-            <con:configuration>
-              <path>$.importedPlanIds</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="493b851d-f4cf-4289-90b8-3cb49d482b72" name="linksExists">
-            <con:configuration>
-              <path>$.links</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -21239,24 +21935,6 @@ if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "VALIDATION_FAILED" ){
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Match" id="d7f0823c-c0f0-46b2-8c85-26b6e828a833" name="importedPlanIds">
-            <con:configuration>
-              <path>$.importedPlanIds</path>
-              <content>null</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
-          <con:assertion type="JsonPath Match" id="69eedd5e-af1f-4496-9645-974bd7cf8191" name="links">
-            <con:configuration>
-              <path>$.links</path>
-              <content>null</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -21394,6 +22072,26 @@ if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "VALIDATION_FAILED" ){
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
+          <con:assertion type="JsonPath RegEx Match" id="39a75872-c3c6-4fe9-ac53-858e3008c208" name="link self">
+            <con:configuration>
+              <path>$[0].links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+              <content>true</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+              <regEx>^.*/api/v1/plan/.*$</regEx>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath RegEx Match" id="39a75872-c3c6-4fe9-ac53-858e3008c208" name="link planwerkwms">
+            <con:configuration>
+              <path>$[0].links[?(@.rel == 'planwerkwms')].href</path>
+              <content>true</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+              <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+            </con:configuration>
+          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -21471,6 +22169,26 @@ if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "VALIDATION_FAILED" ){
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
+          <con:assertion type="JsonPath RegEx Match" id="c4de6278-26a0-4499-b07a-a01eb57cafd2" name="link self">
+            <con:configuration>
+              <path>$[0].links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+              <content>true</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+              <regEx>^.*/api/v1/plan/.*$</regEx>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath RegEx Match" id="c4de6278-26a0-4499-b07a-a01eb57cafd2" name="link planwerkwms">
+            <con:configuration>
+              <path>$[0].links[?(@.rel == 'planwerkwms')].href</path>
+              <content>true</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+              <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+            </con:configuration>
+          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -25199,6 +25917,26 @@ if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "VALIDATION_FAILED" ){
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
+          <con:assertion type="JsonPath RegEx Match" id="ef5b8e76-d4eb-4b91-a20f-cfacbdaaa3d3" name="link self">
+            <con:configuration>
+              <path>$.links[?(@.rel == 'self' &amp;&amp; @.type == 'application/json')].href</path>
+              <content>false</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+              <regEx>^.*/api/v1/plan/.*$</regEx>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath RegEx Match" id="ef5b8e76-d4eb-4b91-a20f-cfacbdaaa3d3" name="link planwerkwms">
+            <con:configuration>
+              <path>$.links[?(@.rel == 'planwerkwms')].href</path>
+              <content>true</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+              <regEx>^.*/services/planwerkwms/planname/.*$</regEx>
+            </con:configuration>
+          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -25653,33 +26391,6 @@ if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "VALIDATION_FAILED" ){
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="129ac743-0353-43ba-93a5-97580a06afee" name="errorMsgExists">
-            <con:configuration>
-              <path>$.errorMsg</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="320f668b-21ff-4589-a944-cfbd07931e2a" name="importedPlanIdsExists">
-            <con:configuration>
-              <path>$.importedPlanIds</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="493b851d-f4cf-4289-90b8-3cb49d482b72" name="linksExists">
-            <con:configuration>
-              <path>$.links</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -25738,15 +26449,6 @@ if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "IMPORT_FINISHED" ){
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="129ac743-0353-43ba-93a5-97580a06afee" name="errorMsgExists">
-            <con:configuration>
-              <path>$.errorMsg</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
           <con:assertion type="JsonPath Existence Match" id="320f668b-21ff-4589-a944-cfbd07931e2a" name="importedPlanIdsExists">
             <con:configuration>
               <path>$.importedPlanIds</path>
@@ -26132,33 +26834,6 @@ if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "IMPORT_FINISHED" ){
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="129ac743-0353-43ba-93a5-97580a06afee" name="errorMsgExists">
-            <con:configuration>
-              <path>$.errorMsg</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="320f668b-21ff-4589-a944-cfbd07931e2a" name="importedPlanIdsExists">
-            <con:configuration>
-              <path>$.importedPlanIds</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="493b851d-f4cf-4289-90b8-3cb49d482b72" name="linksExists">
-            <con:configuration>
-              <path>$.links</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -26184,7 +26859,7 @@ def json = new JsonSlurper().parseText(response)
 if( context.loopIndex == null )
 	context.loopIndex = 0
 
-if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "VALIDATION_FINISHED" ){
+if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "IMPORT_ABORTED" ){
 	sleep(1000)
 	testRunner.gotoStepByName(testStepName)
 } else if (context.loopIndex == 40) {
@@ -26211,7 +26886,7 @@ if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "VALIDATION_FINISHED"
           <con:assertion type="JsonPath Match" id="d27fd88e-b78e-4e28-acfc-dc25276fc1a1" name="status">
             <con:configuration>
               <path>$.status</path>
-              <content>VALIDATION_FINISHED</content>
+              <content>IMPORT_ABORTED</content>
               <allowWildcards>false</allowWildcards>
               <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
               <ignoreComments>false</ignoreComments>
@@ -26226,15 +26901,6 @@ if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "VALIDATION_FINISHED"
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="320f668b-21ff-4589-a944-cfbd07931e2a" name="importedPlanIdsExists">
-            <con:configuration>
-              <path>$.importedPlanIds</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
           <con:assertion type="JsonPath Existence Match" id="493b851d-f4cf-4289-90b8-3cb49d482b72" name="linksExists">
             <con:configuration>
               <path>$.links</path>
@@ -26483,33 +27149,6 @@ if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "VALIDATION_FINISHED"
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="129ac743-0353-43ba-93a5-97580a06afee" name="errorMsgExists">
-            <con:configuration>
-              <path>$.errorMsg</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="320f668b-21ff-4589-a944-cfbd07931e2a" name="importedPlanIdsExists">
-            <con:configuration>
-              <path>$.importedPlanIds</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="493b851d-f4cf-4289-90b8-3cb49d482b72" name="linksExists">
-            <con:configuration>
-              <path>$.links</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -26535,7 +27174,7 @@ def json = new JsonSlurper().parseText(response)
 if( context.loopIndex == null )
 	context.loopIndex = 0
 
-if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "VALIDATION_FINISHED" ){
+if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "IMPORT_ABORTED" ){
 	sleep(1000)
 	testRunner.gotoStepByName(testStepName)
 } else if (context.loopIndex == 40) {
@@ -26562,7 +27201,7 @@ if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "VALIDATION_FINISHED"
           <con:assertion type="JsonPath Match" id="d27fd88e-b78e-4e28-acfc-dc25276fc1a1" name="status">
             <con:configuration>
               <path>$.status</path>
-              <content>VALIDATION_FINISHED</content>
+              <content>IMPORT_ABORTED</content>
               <allowWildcards>false</allowWildcards>
               <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
               <ignoreComments>false</ignoreComments>
@@ -26577,15 +27216,6 @@ if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "VALIDATION_FINISHED"
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="320f668b-21ff-4589-a944-cfbd07931e2a" name="importedPlanIdsExists">
-            <con:configuration>
-              <path>$.importedPlanIds</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
           <con:assertion type="JsonPath Existence Match" id="493b851d-f4cf-4289-90b8-3cb49d482b72" name="linksExists">
             <con:configuration>
               <path>$.links</path>
@@ -26916,33 +27546,6 @@ assert json.version != null</scriptText>
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="129ac743-0353-43ba-93a5-97580a06afee" name="errorMsgExists">
-            <con:configuration>
-              <path>$.errorMsg</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="320f668b-21ff-4589-a944-cfbd07931e2a" name="importedPlanIdsExists">
-            <con:configuration>
-              <path>$.importedPlanIds</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="493b851d-f4cf-4289-90b8-3cb49d482b72" name="linksExists">
-            <con:configuration>
-              <path>$.links</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -27001,15 +27604,6 @@ if( ++context.loopIndex &lt; 40 &amp;&amp; json.status != "IMPORT_FINISHED" ){
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="129ac743-0353-43ba-93a5-97580a06afee" name="errorMsgExists">
-            <con:configuration>
-              <path>$.errorMsg</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
           <con:assertion type="JsonPath Existence Match" id="320f668b-21ff-4589-a944-cfbd07931e2a" name="importedPlanIdsExists">
             <con:configuration>
               <path>$.importedPlanIds</path>
diff --git a/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-manager-api/plans/BPlan004_6-0_ValidationError.zip b/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-manager-api/plans/BPlan004_6-0_ValidationError.zip
new file mode 100644
index 0000000000000000000000000000000000000000..06fa4116aa23d58d447fab879da528895a7e6767
Binary files /dev/null and b/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-manager-api/plans/BPlan004_6-0_ValidationError.zip differ
diff --git a/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-validator-api-soapui-project.xml b/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-validator-api-soapui-project.xml
index 06d405013046ba940c7caf3d9367237b70a38b58..062c88f9b7f7c714417ef4b90fd9b547ef0275d7 100644
--- a/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-validator-api-soapui-project.xml
+++ b/xplan-tests/xplan-tests-soapui/src/main/resources/xplan-validator-api-soapui-project.xml
@@ -930,6 +930,15 @@ assert json.version != null</scriptText>
                 <ignoreComments>false</ignoreComments>
               </con:configuration>
             </con:assertion>
+            <con:assertion type="JsonPath Existence Match" id="a58def7e-d4c5-4950-9d34-d863b1786790" name="skipRasterEvaluationExists">
+              <con:configuration>
+                <path>$.skipRasterEvaluation</path>
+                <content>true</content>
+                <allowWildcards>false</allowWildcards>
+                <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+                <ignoreComments>false</ignoreComments>
+              </con:configuration>
+            </con:assertion>
             <con:credentials>
               <con:username>${#Project#username}</con:username>
               <con:password>${#Project#password}</con:password>
@@ -4061,18 +4070,27 @@ assert json.version != null</scriptText>
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Match" id="ea1e9aa3-fbc6-40ca-aa79-d819f45463e0" name="externalReferencesResult.crsStatus">
+          <con:assertion type="JsonPath Match" id="ea1e9aa3-fbc6-40ca-aa79-d819f45463e0" name="rasterEvaluationResults.name">
+            <con:configuration>
+              <path>$.rasterEvaluationResults[?(@.name == "BPlan004_6-0.png")].name</path>
+              <content>[BPlan004_6-0.png]</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="ea1e9aa3-fbc6-40ca-aa79-d819f45463e0" name="rasterEvaluationResults.crsStatus">
             <con:configuration>
-              <path>$.externalReferencesResult[?(@.name == "BPlan004_6-0.png")].crsStatus</path>
+              <path>$.rasterEvaluationResults[?(@.name == "BPlan004_6-0.png")].crsStatus</path>
               <content>[MISSING]</content>
               <allowWildcards>false</allowWildcards>
               <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Match" id="ea1e9aa3-fbc6-40ca-aa79-d819f45463e0" name="externalReferencesResult.imageFormatStatus">
+          <con:assertion type="JsonPath Match" id="ea1e9aa3-fbc6-40ca-aa79-d819f45463e0" name="rasterEvaluationResults.imageFormatStatus">
             <con:configuration>
-              <path>$.externalReferencesResult[?(@.name == "BPlan004_6-0.png")].imageFormatStatus</path>
+              <path>$.rasterEvaluationResults[?(@.name == "BPlan004_6-0.png")].imageFormatStatus</path>
               <content>[SUPPORTED]</content>
               <allowWildcards>false</allowWildcards>
               <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
@@ -4130,6 +4148,15 @@ assert json.version != null</scriptText>
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
+          <con:assertion type="JsonPath Match" id="0b6b03f1-a915-4798-b536-a3d3127dac7c" name="rasterEvaluationResults">
+            <con:configuration>
+              <path>$.rasterEvaluationResults</path>
+              <content>[]</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -4181,18 +4208,27 @@ assert json.version != null</scriptText>
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Match" id="ea1e9aa3-fbc6-40ca-aa79-d819f45463e0" name="externalReferencesResult.crsStatus">
+          <con:assertion type="JsonPath Match" id="ea1e9aa3-fbc6-40ca-aa79-d819f45463e0" name="rasterEvaluationResults.name">
+            <con:configuration>
+              <path>$.rasterEvaluationResults[?(@.name == "BPlan006_6-0.tiff")].name</path>
+              <content>[BPlan006_6-0.tiff]</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="ea1e9aa3-fbc6-40ca-aa79-d819f45463e0" name="rasterEvaluationResults.crsStatus">
             <con:configuration>
-              <path>$.externalReferencesResult[?(@.name == "BPlan006_6-0.tiff")].crsStatus</path>
+              <path>$.rasterEvaluationResults[?(@.name == "BPlan006_6-0.tiff")].crsStatus</path>
               <content>[UNSUPPORTED]</content>
               <allowWildcards>false</allowWildcards>
               <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Match" id="ea1e9aa3-fbc6-40ca-aa79-d819f45463e0" name="externalReferencesResult.imageFormatStatus">
+          <con:assertion type="JsonPath Match" id="ea1e9aa3-fbc6-40ca-aa79-d819f45463e0" name="rasterEvaluationResults.imageFormatStatus">
             <con:configuration>
-              <path>$.externalReferencesResult[?(@.name == "BPlan006_6-0.tiff")].imageFormatStatus</path>
+              <path>$.rasterEvaluationResults[?(@.name == "BPlan006_6-0.tiff")].imageFormatStatus</path>
               <content>[SUPPORTED]</content>
               <allowWildcards>false</allowWildcards>
               <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
@@ -4569,6 +4605,15 @@ assert json.version != null</scriptText>
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
+          <con:assertion type="JsonPath Match" id="a1e8c528-a99c-429d-84e4-3c0a1371aae2" name="path /validate response 200 description">
+            <con:configuration>
+              <path>$.paths./validate.post.responses.200.description</path>
+              <content>ValidationReceipt with uuid of the validation</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
           <con:assertion type="JsonPath Match" id="3a711a3a-80f6-4f4b-92d2-412784d41ae8" name="path /status/{uuid}">
             <con:configuration>
               <path>$.paths./status/{uuid}.get.operationId</path>
@@ -4709,6 +4754,15 @@ assert json.version != null</scriptText>
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
+          <con:assertion type="JsonPath Existence Match" id="5e0f825a-e774-4dcc-ba6e-c6d88cb8e55d" name="skipRasterEvaluationExists">
+            <con:configuration>
+              <path>$.skipRasterEvaluation</path>
+              <content>true</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -5070,15 +5124,6 @@ assert json.version != null</scriptText>
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="9c15ee46-6bc7-4cb2-bca6-6439ca6fdd4f" name="linksExists">
-            <con:configuration>
-              <path>$.links</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -5157,6 +5202,36 @@ if( ++context.loopIndex &lt; 20 &amp;&amp; json.status != "VALIDATION_FINISHED"
               <regEx>(.*).json|(.*).pdf</regEx>
             </con:configuration>
           </con:assertion>
+          <con:assertion type="JsonPath RegEx Match" id="c1bbab33-617a-4d60-abf6-25aa6c87f865" name="schema report">
+            <con:configuration>
+              <path>$.links[?(@.rel == 'report' &amp;&amp; @.type == 'application/json')].schema</path>
+              <content>true</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+              <regEx>^.*/api/v2#/components/schemas/ValidationReport.*$</regEx>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath RegEx Match" id="2e5ee3a4-3456-4e7c-9544-f9a2a765a96e" name="href report json">
+            <con:configuration>
+              <path>$.links[?(@.rel == 'report' &amp;&amp; @.type == 'application/json')].href</path>
+              <content>true</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+              <regEx>^.*report.json.*$</regEx>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath RegEx Match" id="2e5ee3a4-3456-4e7c-9544-f9a2a765a96e" name="href report pdf">
+            <con:configuration>
+              <path>$.links[?(@.rel == 'report' &amp;&amp; @.type == 'application/pdf')].href</path>
+              <content>true</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+              <regEx>^.*report.pdf.*$</regEx>
+            </con:configuration>
+          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -5259,15 +5334,6 @@ testRunner.testCase.setPropertyValue( "reportPdf", hrefPdf )</script>
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Match" id="095b0bb8-5f84-4622-bce5-36deb4f29499" name="linksExists">
-            <con:configuration>
-              <path>$.links</path>
-              <content>null</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -5335,15 +5401,6 @@ if( ++context.loopIndex &lt; 20 &amp;&amp; json.status != "VALIDATION_FAILED" ){
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Match" id="095b0bb8-5f84-4622-bce5-36deb4f29499" name="links">
-            <con:configuration>
-              <path>$.links</path>
-              <content>null</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -5596,15 +5653,6 @@ if( ++context.loopIndex &lt; 20 &amp;&amp; json.status != "VALIDATION_FAILED" ){
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="9c15ee46-6bc7-4cb2-bca6-6439ca6fdd4f" name="linksExists">
-            <con:configuration>
-              <path>$.links</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -5945,15 +5993,6 @@ testRunner.testCase.setPropertyValue( "reportPdf", hrefPdf )</script>
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="9c15ee46-6bc7-4cb2-bca6-6439ca6fdd4f" name="linksExists">
-            <con:configuration>
-              <path>$.links</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -6261,15 +6300,6 @@ testRunner.testCase.setPropertyValue( "reportPdf", hrefPdf )</script>
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="9c15ee46-6bc7-4cb2-bca6-6439ca6fdd4f" name="linksExists">
-            <con:configuration>
-              <path>$.links</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
@@ -6652,15 +6682,6 @@ testRunner.testCase.setPropertyValue( "reportPdf", hrefPdf )</script>
               <ignoreComments>false</ignoreComments>
             </con:configuration>
           </con:assertion>
-          <con:assertion type="JsonPath Existence Match" id="9c15ee46-6bc7-4cb2-bca6-6439ca6fdd4f" name="linksExists">
-            <con:configuration>
-              <path>$.links</path>
-              <content>true</content>
-              <allowWildcards>false</allowWildcards>
-              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
-              <ignoreComments>false</ignoreComments>
-            </con:configuration>
-          </con:assertion>
           <con:credentials>
             <con:username>${#Project#username}</con:username>
             <con:password>${#Project#password}</con:password>
diff --git a/xplan-validator/xplan-validator-api/.trivyignore b/xplan-validator/xplan-validator-api/.trivyignore
index 3bdef816df8ab974c21ae560fcee5f6da8099bc6..a89d1b4a1aa6b42ed031bd1a456b6d2db778e3d3 100644
--- a/xplan-validator/xplan-validator-api/.trivyignore
+++ b/xplan-validator/xplan-validator-api/.trivyignore
@@ -1 +1 @@
-CVE-2016-1000027
\ No newline at end of file
+# no issue to ignore currently
\ No newline at end of file
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/config/ApplicationContext.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/config/ApplicationContext.java
index 39bde8783c63127e1c3289d08b569b792a651c8e..06ae89a9ed4649391f176ee8dbbe7be604ed8a10 100644
--- a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/config/ApplicationContext.java
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/config/ApplicationContext.java
@@ -50,7 +50,7 @@ import de.latlon.xplan.validator.syntactic.SyntacticValidator;
 import de.latlon.xplan.validator.syntactic.SyntacticValidatorImpl;
 import de.latlon.xplanbox.api.commons.handler.SystemConfigHandler;
 import de.latlon.xplanbox.security.config.SecurityContext;
-import de.latlon.xplanbox.validator.storage.config.AmazonS3Context;
+import de.latlon.xplanbox.validator.storage.config.AmazonS3ValidationContext;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
@@ -64,7 +64,7 @@ import org.springframework.core.io.ResourceLoader;
  */
 @Configuration
 @ComponentScan(basePackages = { "de.latlon.xplanbox.api.validator.handler", "de.latlon.xplanbox.api.validator.v1" })
-@Import({ SecurityContext.class, AmazonS3Context.class })
+@Import({ SecurityContext.class, AmazonS3ValidationContext.class })
 public class ApplicationContext {
 
 	@Autowired
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/handler/ConfigHandler.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/handler/ConfigHandler.java
index 414b185c5da0c21d597fc4270802734d160a01d7..05195cf7b585288d57ced255cd1533e7f87db222 100644
--- a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/handler/ConfigHandler.java
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/handler/ConfigHandler.java
@@ -20,17 +20,18 @@
  */
 package de.latlon.xplanbox.api.validator.handler;
 
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.io.IOException;
+
 import de.latlon.xplanbox.api.commons.handler.SystemConfigHandler;
 import de.latlon.xplanbox.api.commons.v1.model.SystemConfig;
+import de.latlon.xplanbox.api.validator.config.ValidatorApiConfiguration;
+import jakarta.inject.Singleton;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import jakarta.inject.Singleton;
-import java.io.IOException;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
  */
@@ -43,12 +44,16 @@ public class ConfigHandler {
 	@Autowired
 	private SystemConfigHandler systemConfigHandler;
 
+	@Autowired
+	private ValidatorApiConfiguration validatorApiConfiguration;
+
 	public SystemConfig describeSystem() throws IOException {
 		LOG.debug("Generating validator config information");
 		return new SystemConfig().version(parseVersion())
 			.rulesMetadata(systemConfigHandler.getRulesMetadata())
 			.profiles(systemConfigHandler.getProfiles())
-			.supportedXPlanGmlVersions(systemConfigHandler.allSupportedVersions());
+			.supportedXPlanGmlVersions(systemConfigHandler.allSupportedVersions())
+			.skipRasterEvaluation(validatorApiConfiguration.isSkipRasterEvaluation());
 	}
 
 	public String parseVersion() {
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/handler/v2/ConfigHandlerV2.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/handler/v2/ConfigHandlerV2.java
index bec7c59d053cbf1a913e2019edb98d8e7daf96b5..5c51bf7691b45a7be6110396062570064eb2553d 100644
--- a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/handler/v2/ConfigHandlerV2.java
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/handler/v2/ConfigHandlerV2.java
@@ -27,6 +27,7 @@ import java.util.List;
 
 import de.latlon.xplanbox.api.commons.handler.SystemConfigHandler;
 import de.latlon.xplanbox.api.commons.v2.model.SystemConfig;
+import de.latlon.xplanbox.api.validator.config.ValidatorApiConfiguration;
 import jakarta.inject.Singleton;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -48,11 +49,15 @@ public class ConfigHandlerV2 {
 	@Autowired
 	private SystemConfigHandler systemConfigHandler;
 
+	@Autowired
+	private ValidatorApiConfiguration validatorApiConfiguration;
+
 	public SystemConfig describeSystem() throws IOException {
 		LOG.debug("Generating validator config information");
 		return new SystemConfig().version(parseVersion())
 			.profiles(activatedProfiles)
-			.supportedXPlanGmlVersions(systemConfigHandler.allSupportedVersions());
+			.supportedXPlanGmlVersions(systemConfigHandler.allSupportedVersions())
+			.skipRasterEvaluation(validatorApiConfiguration.isSkipRasterEvaluation());
 	}
 
 	public String parseVersion() {
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v1/ValidateApi.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v1/ValidateApi.java
index 991e0fe1caf33996910d7f18162722c5b56d4fcd..8008a6b90cb290cc39ce1c527ff52edf13ce95ba 100644
--- a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v1/ValidateApi.java
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v1/ValidateApi.java
@@ -24,10 +24,10 @@ import static de.latlon.xplan.commons.util.ContentTypeChecker.checkContentTypesO
 import static de.latlon.xplan.commons.util.TextPatternConstants.SIMPLE_NAME_PATTERN;
 import static de.latlon.xplanbox.api.commons.ValidatorConverter.createValidationSettings;
 import static de.latlon.xplanbox.api.commons.ValidatorConverter.detectOrCreateValidationName;
-import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.APPLICATION_PDF;
-import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.APPLICATION_PDF_TYPE;
-import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.APPLICATION_ZIP;
-import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.APPLICATION_ZIP_TYPE;
+import static de.latlon.xplanbox.api.commons.XPlanMediaType.APPLICATION_PDF;
+import static de.latlon.xplanbox.api.commons.XPlanMediaType.APPLICATION_PDF_TYPE;
+import static de.latlon.xplanbox.api.commons.XPlanMediaType.APPLICATION_ZIP;
+import static de.latlon.xplanbox.api.commons.XPlanMediaType.APPLICATION_ZIP_TYPE;
 import static de.latlon.xplanbox.validator.storage.StatusType.VALIDATION_REQUESTED;
 import static io.swagger.v3.oas.annotations.enums.Explode.FALSE;
 import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/StatusApi.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/StatusApi.java
index c4aafc048c5e716e5345276aa85b106ea406e4c6..0da606001d10c4b5a711e836febb81b539c4e5ea 100644
--- a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/StatusApi.java
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/StatusApi.java
@@ -29,8 +29,10 @@ import java.net.URISyntaxException;
 import de.latlon.xplan.commons.s3.StorageException;
 import de.latlon.xplanbox.api.commons.exception.InvalidValidationUuid;
 import de.latlon.xplanbox.api.commons.v2.model.ResponseLink;
-import de.latlon.xplanbox.api.commons.v2.model.StatusEnum;
-import de.latlon.xplanbox.api.commons.v2.model.StatusNotification;
+import de.latlon.xplanbox.api.commons.v2.model.ValidationReport;
+import de.latlon.xplanbox.api.validator.config.ValidatorApiConfiguration;
+import de.latlon.xplanbox.api.validator.v2.model.StatusEnum;
+import de.latlon.xplanbox.api.validator.v2.model.ValidationStatusNotification;
 import de.latlon.xplanbox.validator.storage.Status;
 import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
 import io.swagger.v3.oas.annotations.Operation;
@@ -55,6 +57,9 @@ public class StatusApi {
 	@Autowired
 	private ValidationExecutionStorage validationExecutionStorage;
 
+	@Autowired
+	private ValidatorApiConfiguration validatorApiConfiguration;
+
 	@GET
 	@Produces({ "application/json" })
 	@Path("/{uuid}")
@@ -63,7 +68,7 @@ public class StatusApi {
 			responses = {
 					@ApiResponse(responseCode = "200", description = "StatusNotification",
 							content = { @Content(mediaType = APPLICATION_JSON,
-									schema = @Schema(implementation = StatusNotification.class)) }),
+									schema = @Schema(implementation = ValidationStatusNotification.class)) }),
 					@ApiResponse(responseCode = "404",
 							description = "Invalid uuid, no validation with the passed uuid found"),
 					@ApiResponse(responseCode = "406", description = "Requested format is not available") })
@@ -83,13 +88,14 @@ public class StatusApi {
 		}
 	}
 
-	public StatusNotification fromStatus(Status status) throws URISyntaxException {
-		StatusNotification statusNotification = new StatusNotification()
+	public ValidationStatusNotification fromStatus(Status status) throws URISyntaxException {
+		ValidationStatusNotification statusNotification = (ValidationStatusNotification) new ValidationStatusNotification()
 			.status(StatusEnum.valueOf(status.getStatusType().name()))
 			.errorMsg(status.getErrorMsg());
 		if (status.getLinkToJsonReport() != null)
 			statusNotification.links(
 					(ResponseLink) new ResponseLink().rel(REPORT)
+						.schema(createLinkToSchema())
 						.expirationTime(status.getExpirationTime())
 						.type("application/json")
 						.title("Validierungsreport")
@@ -102,4 +108,11 @@ public class StatusApi {
 		return statusNotification;
 	}
 
+	private URI createLinkToSchema() {
+		URI apiUrl = validatorApiConfiguration.getApiUrl();
+		if (apiUrl == null)
+			return null;
+		return apiUrl.resolve("api/v2#/components/schemas/" + ValidationReport.class.getSimpleName());
+	}
+
 }
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 afcd343b02065643ef20cc51f1907c4efa78e465..83961d901a3968d4a00de1b36368eb2586ec8731 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
@@ -95,7 +95,7 @@ public class ValidateApi2 {
 	@Operation(summary = "Validate XPlanGML or XPlanArchive", description = "Validates XPlanGML or XPlanArchive file",
 			tags = { "validate" },
 			responses = {
-					@ApiResponse(responseCode = "200", description = "ValidationReport",
+					@ApiResponse(responseCode = "200", description = "ValidationReceipt with uuid of the validation",
 							content = { @Content(mediaType = APPLICATION_JSON,
 									schema = @Schema(implementation = ValidationReceipt.class)) }),
 					@ApiResponse(responseCode = "400", description = "Invalid input"),
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/model/StatusEnum.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/model/StatusEnum.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4277d505e2e80ed4a57f0605d0d63595d84ca15
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/model/StatusEnum.java
@@ -0,0 +1,21 @@
+package de.latlon.xplanbox.api.validator.v2.model;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+public enum StatusEnum {
+
+	// Validation requested
+	VALIDATION_REQUESTED,
+
+	// Validation started
+	VALIDATION_STARTED,
+
+	// Validation failed
+	VALIDATION_FAILED,
+
+	// Validation finished
+	VALIDATION_FINISHED
+
+}
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/model/ValidationStatusNotification.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/model/ValidationStatusNotification.java
new file mode 100644
index 0000000000000000000000000000000000000000..b39a4ab092a76a068d8a4394ee4b66104c8ea4a3
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/model/ValidationStatusNotification.java
@@ -0,0 +1,31 @@
+package de.latlon.xplanbox.api.validator.v2.model;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+public class ValidationStatusNotification extends de.latlon.xplanbox.api.commons.v2.model.StatusNotification {
+
+	private StatusEnum status;
+
+	public ValidationStatusNotification() {
+	}
+
+	public ValidationStatusNotification(StatusEnum status) {
+		this.status = status;
+	}
+
+	public StatusEnum getStatus() {
+		return status;
+	}
+
+	public void setStatus(StatusEnum status) {
+		this.status = status;
+	}
+
+	public ValidationStatusNotification status(StatusEnum status) {
+		this.status = status;
+		return this;
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/config/TestContext.java b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/config/TestContext.java
index a3e9f8573e92c567197a280aac4a7326fa3e1395..486abfdfc36322375163a4013e64b90c6218ec9b 100644
--- a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/config/TestContext.java
+++ b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/config/TestContext.java
@@ -26,17 +26,12 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 import static org.slf4j.LoggerFactory.getLogger;
 
-import java.io.IOException;
-import java.util.Optional;
-
 import de.latlon.core.validator.events.EventSender;
 import de.latlon.xplan.commons.archive.SemanticValidableXPlanArchive;
 import de.latlon.xplan.validator.semantic.configuration.metadata.RulesMetadata;
 import de.latlon.xplan.validator.semantic.profile.SemanticProfileValidator;
 import de.latlon.xplan.validator.semantic.profile.SemanticProfiles;
 import de.latlon.xplan.validator.semantic.report.SemanticValidatorResult;
-import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
-import de.latlon.xplanbox.validator.storage.filesystem.FileSystemValidationExecutionStorage;
 import jakarta.annotation.PostConstruct;
 import org.mockito.Mockito;
 import org.slf4j.Logger;
@@ -84,11 +79,6 @@ public class TestContext {
 		return new FakeAsyncValidationWrapper();
 	}
 
-	@Bean
-	public ValidationExecutionStorage validationExecutionStorage() throws IOException {
-		return new FileSystemValidationExecutionStorage(Optional.empty());
-	}
-
 	private static SemanticProfileValidator createValidator(RulesMetadata profile) {
 		SemanticProfileValidator semanticProfileValidator = mock(SemanticProfileValidator.class);
 		when(semanticProfileValidator.getId()).thenReturn(profile.getId());
diff --git a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v1/InfoApiTest.java b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v1/InfoApiTest.java
index dfa69f1fa27bf67e74463cecc74a7ccbae98cc4f..a6b22e061942a63449ef8675aa092743deb7d131 100644
--- a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v1/InfoApiTest.java
+++ b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v1/InfoApiTest.java
@@ -63,6 +63,7 @@ class InfoApiTest extends ValidatorApiJerseyTest {
 
 		assertThat(response).contains("supportedXPlanGmlVersions");
 		assertThat(response).contains("profiles");
+		assertThat(response).contains("skipRasterEvaluation");
 	}
 
 }
diff --git a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v1/ValidateApiJerseyTest.java b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v1/ValidateApiJerseyTest.java
index b244ae182984badcf5eb26e8daf188a980629031..dc1fed2e4380bcabd851971bb03574609c2a5e4c 100644
--- a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v1/ValidateApiJerseyTest.java
+++ b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v1/ValidateApiJerseyTest.java
@@ -20,9 +20,9 @@
  */
 package de.latlon.xplanbox.api.validator.v1;
 
-import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.APPLICATION_X_ZIP;
-import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.APPLICATION_X_ZIP_COMPRESSED;
-import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.APPLICATION_ZIP;
+import static de.latlon.xplanbox.api.commons.XPlanMediaType.APPLICATION_X_ZIP;
+import static de.latlon.xplanbox.api.commons.XPlanMediaType.APPLICATION_X_ZIP_COMPRESSED;
+import static de.latlon.xplanbox.api.commons.XPlanMediaType.APPLICATION_ZIP;
 import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
 import static jakarta.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
 import static jakarta.ws.rs.core.MediaType.APPLICATION_XML;
diff --git a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v2/ValidateApi2Test.java b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v2/ValidateApi2Test.java
index c75d6b1456a2e9f4dbbceb091989192f6e672154..d7df1153dd779a027fee1551d5ed0c3a14e08477 100644
--- a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v2/ValidateApi2Test.java
+++ b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v2/ValidateApi2Test.java
@@ -20,7 +20,7 @@
  */
 package de.latlon.xplanbox.api.validator.v2;
 
-import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.APPLICATION_X_ZIP_COMPRESSED;
+import static de.latlon.xplanbox.api.commons.XPlanMediaType.APPLICATION_X_ZIP_COMPRESSED;
 import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
 import static jakarta.ws.rs.core.MediaType.TEXT_XML;
 import static org.assertj.core.api.Assertions.assertThat;
diff --git a/xplan-validator/xplan-validator-api/src/test/resources/s3Mock.properties b/xplan-validator/xplan-validator-api/src/test/resources/s3Mock.properties
index 93570b0759b71cdd5e78970bece6c9761b01db06..e761625d13aea69903a7a6541161bf15c78474a5 100644
--- a/xplan-validator/xplan-validator-api/src/test/resources/s3Mock.properties
+++ b/xplan-validator/xplan-validator-api/src/test/resources/s3Mock.properties
@@ -23,3 +23,5 @@ xplanbox.s3.secretKey=
 xplanbox.validation.s3.bucketName=latlonvalidationtest
 xplanbox.s3.region=eu-central-1
 xplanbox.s3.endpoint.url=http://localhost
+
+xplanbox.validation.s3.bucketPublicUrl=http://localhost/test
\ No newline at end of file
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 29965a8e77a63051ed0d68477e5e009f915d7f79..d77f80834bc076f2714e70ae1c235dc1e2739fa0 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
@@ -15,8 +15,8 @@ import java.util.Map;
 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.XPlanboxPublicV1Event;
-import de.latlon.core.validator.events.v1.XPlanboxPublicV1Event.EventType;
+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.ValidatorReport;
@@ -70,14 +70,14 @@ public class PlanValidator {
 	private ValidationReport validate(ValidationRequestedEvent event, boolean cleanUp) throws Exception {
 		validationExecutionStorage.changeStatus(event.getUuid(), StatusType.VALIDATION_STARTED);
 		eventSender.sendPublicEvent(
-				new XPlanboxPublicV1Event(EventType.VALIDATION_STARTED, event.getUuid(), "validation started"));
+				new XPlanPublicV1Event(EventType.VALIDATION_STARTED, event.getUuid(), "validation started"));
 
 		try {
 			return doValidate(event, cleanUp);
 		}
 		finally {
 			eventSender.sendPublicEvent(
-					new XPlanboxPublicV1Event(EventType.VALIDATION_FINISHED, event.getUuid(), "validation finished"));
+					new XPlanPublicV1Event(EventType.VALIDATION_FINISHED, event.getUuid(), "validation finished"));
 		}
 	}
 
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 d62cabc3ef93a991bc82bf842699b89c6cc245d8..39c79431731a67e89a6e85d678bf27a57fb3a55f 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
@@ -49,10 +49,9 @@ import de.latlon.xplan.validator.semantic.xquery.XQuerySemanticValidator;
 import de.latlon.xplan.validator.syntactic.SyntacticValidator;
 import de.latlon.xplan.validator.syntactic.SyntacticValidatorImpl;
 import de.latlon.xplan.validator.wms.config.ValidatorWmsContext;
-import de.latlon.xplanbox.api.commons.handler.SystemConfigHandler;
 import de.latlon.xplanbox.core.raster.config.RasterEvaluationContext;
 import de.latlon.xplanbox.core.raster.evaluation.XPlanRasterEvaluator;
-import de.latlon.xplanbox.validator.storage.config.AmazonS3Context;
+import de.latlon.xplanbox.validator.storage.config.AmazonS3ValidationContext;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
@@ -65,18 +64,12 @@ import org.springframework.core.io.ResourceLoader;
  * @since 8.0
  */
 @Configuration
-@Import({ ValidatorWmsContext.class, AmazonS3Context.class, RasterEvaluationContext.class })
+@Import({ ValidatorWmsContext.class, AmazonS3ValidationContext.class, RasterEvaluationContext.class })
 public class ApplicationContext {
 
 	@Autowired
 	private ResourceLoader resourceLoader;
 
-	@Bean
-	public SystemConfigHandler systemConfigHandler(XQuerySemanticValidatorConfigurationRetriever configurationRetriever,
-			SemanticProfiles semanticProfiles) {
-		return new SystemConfigHandler(configurationRetriever, semanticProfiles.getProfileMetadata());
-	}
-
 	@Bean
 	public Path uploadFolder() throws IOException {
 		return createTempDirectory("xplan-validator");
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 edb62ffab5d67095bbcfef6bc81f3309d29a60d5..4b0757a2be5a84352c409dd9fa908eb92b3f3f70 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
@@ -98,14 +98,7 @@ public class Receiver {
 			ImportRequestedEvent importRequestedEvent = new ImportRequestedEvent(event.getUuid(),
 					event.getSettings().getValidationName(), event.getInternalId(), event.getPlanStatus(),
 					event.getOriginFile(), validationReport.getValid() ? VALID : INVALID,
-					validationReport.getExternalReferencesResult()
-						.stream()
-						.anyMatch(externalReferenceResult -> externalReferenceResult
-							.getStatus() == ExternalReferenceStatusEnum.MISSING
-								|| externalReferenceResult.getCrsStatus() == CrsStatusEnum.UNSUPPORTED
-								|| externalReferenceResult.getImageFormatStatus() == ImageFormatStatusEnum.UNSUPPORTED)
-										? MISSING_OR_INVALID : AVAILABLE_AND_VALID,
-					event.isSupportsGetPlanByIdAsZip());
+					rasterEvaluationStatus(validationReport), event.isSupportsGetPlanByIdAsZip());
 			eventSender.sendEvent(importRequestedEvent);
 		}
 		catch (Exception e) {
@@ -118,4 +111,19 @@ public class Receiver {
 		}
 	}
 
+	private static ImportRequestedEvent.EXTERNAL_REFERENCES_RESULT rasterEvaluationStatus(
+			ValidationReport validationReport) {
+		boolean hasMissingExternalReferences = validationReport.getExternalReferencesResult()
+			.stream()
+			.anyMatch(externalReferenceResult -> externalReferenceResult
+				.getStatus() == ExternalReferenceStatusEnum.MISSING);
+		if (hasMissingExternalReferences)
+			return MISSING_OR_INVALID;
+		boolean hasInvalidRasterReferences = validationReport.getRasterEvaluationResults()
+			.stream()
+			.anyMatch(rasterEvaluationResult -> rasterEvaluationResult.getCrsStatus() == CrsStatusEnum.UNSUPPORTED
+					|| rasterEvaluationResult.getImageFormatStatus() == ImageFormatStatusEnum.UNSUPPORTED);
+		return hasInvalidRasterReferences ? MISSING_OR_INVALID : AVAILABLE_AND_VALID;
+	}
+
 }
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 742e302a0ec52024b67b9b25c3c47a3bf6801802..eeb737c6dab64431e88fcfe44545cb77a0826784 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
@@ -42,8 +42,8 @@ import de.latlon.core.validator.events.EventSender;
 import de.latlon.core.validator.events.ValidationRequestedEvent;
 import de.latlon.core.validator.events.ValidationRequestedEvent.MediaType;
 import de.latlon.core.validator.events.ValidationRequestedEvent.OriginFile;
-import de.latlon.core.validator.events.v1.XPlanboxPublicV1Event;
-import de.latlon.core.validator.events.v1.XPlanboxPublicV1Event.EventType;
+import de.latlon.core.validator.events.v1.XPlanPublicV1Event;
+import de.latlon.core.validator.events.v1.XPlanPublicV1Event.EventType;
 import de.latlon.xplan.commons.archive.SemanticValidableXPlanArchive;
 import de.latlon.xplan.validator.semantic.configuration.metadata.RulesMetadata;
 import de.latlon.xplan.validator.semantic.profile.SemanticProfileValidator;
@@ -109,7 +109,7 @@ class PlanValidatorTest {
 	EventSender eventSender;
 
 	@Captor
-	ArgumentCaptor<XPlanboxPublicV1Event> publicEventCaptor;
+	ArgumentCaptor<XPlanPublicV1Event> publicEventCaptor;
 
 	@Autowired
 	PlanValidator validator;
@@ -141,9 +141,9 @@ class PlanValidatorTest {
 
 		verifyExpectedReport(uuid, ReportType.JSON, "report1.expected.json");
 
-		XPlanboxPublicV1Event expectedStartEvent = new XPlanboxPublicV1Event(EventType.VALIDATION_STARTED, uuid,
+		XPlanPublicV1Event expectedStartEvent = new XPlanPublicV1Event(EventType.VALIDATION_STARTED, uuid,
 				"validation started");
-		XPlanboxPublicV1Event expectedFinishedEvent = new XPlanboxPublicV1Event(EventType.VALIDATION_FINISHED, uuid,
+		XPlanPublicV1Event expectedFinishedEvent = new XPlanPublicV1Event(EventType.VALIDATION_FINISHED, uuid,
 				"validation finished");
 		Mockito.verify(eventSender, times(2)).sendPublicEvent(publicEventCaptor.capture());
 		assertThat(publicEventCaptor.getAllValues()).containsExactly(expectedStartEvent, expectedFinishedEvent);
diff --git a/xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report1.expected.json b/xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report1.expected.json
index a211c8cc39edcb9d024830e7c5e189b537c96a72..9b45cfb208a7f948b304c126e11b5618cff23a80 100644
--- a/xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report1.expected.json
+++ b/xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report1.expected.json
@@ -1677,6 +1677,7 @@
             ]
         }
     },
+    "rasterEvaluationResults": [],
     "bbox": {
         "minY": 52.33234200586314,
         "minX": 7.373668092967802,
diff --git a/xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report6.expected.json b/xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report6.expected.json
index b5f7ce090c1f6b10f5fe46259a4cdc3674775ccc..529b0796e6a80be600f687f867d9b6763357e7be 100644
--- a/xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report6.expected.json
+++ b/xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report6.expected.json
@@ -1692,6 +1692,7 @@
       ]
     }
   },
+  "rasterEvaluationResults": [],
   "bbox": {
     "minY": 52.33234200586314,
     "minX": 7.373668092967802,
diff --git a/xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report7.expected.json b/xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report7.expected.json
index b138c22b5d444515765464b83a2ea2da99946c9e..ad146d66f5359e0eac08ec43d7196d2fc5387466 100644
--- a/xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report7.expected.json
+++ b/xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report7.expected.json
@@ -1705,6 +1705,7 @@
       ]
     }
   },
+  "rasterEvaluationResults": [],
   "bbox": {
     "minY": 52.33234200586314,
     "minX": 7.373668092967802,
diff --git a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/Status.java b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/Status.java
index ef60edc9e91135a6cf5de8d823bf8ff1b3555006..3334cdd9d1cb18bb4f03994161699ad51eb20120 100644
--- a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/Status.java
+++ b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/Status.java
@@ -21,11 +21,9 @@ public class Status {
 
 	private String linkToPdfReport;
 
-	private String linkToPlansMetadata;
-
 	private Date expirationTime;
 
-	private List<String> importedPlanIds;
+	private List<Integer> importedPlanIds;
 
 	public Status() {
 	}
@@ -82,19 +80,11 @@ public class Status {
 		return linkToPdfReport;
 	}
 
-	public void setPlanInfoLink(String linkToPlansMetadata) {
-		this.linkToPlansMetadata = linkToPlansMetadata;
-	}
-
-	public String getLinkToPlansMetadata() {
-		return linkToPlansMetadata;
-	}
-
-	public List<String> getImportedPlanIds() {
+	public List<Integer> getImportedPlanIds() {
 		return importedPlanIds;
 	}
 
-	public void setImportedPlanIds(List<String> importedPlanIds) {
+	public void setImportedPlanIds(List<Integer> importedPlanIds) {
 		this.importedPlanIds = importedPlanIds;
 	}
 
diff --git a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/StatusType.java b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/StatusType.java
index 75d0ef691b82f5a089125f778aee6e4c8d5441ed..34dc4f51a92930b0a20bb51565c43c63a606823f 100644
--- a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/StatusType.java
+++ b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/StatusType.java
@@ -24,6 +24,9 @@ public enum StatusType {
 	// Import started
 	IMPORT_STARTED,
 
+	// Import aborted due to incomplete XPlanArchive or invalid XPlanGML
+	IMPORT_ABORTED,
+
 	// Import failed
 	IMPORT_FAILED,
 
diff --git a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/StoredImportedPlans.java b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/StoredImportedPlans.java
deleted file mode 100644
index 65b7e69dc83778d7cbad9ba27c438dcb416333db..0000000000000000000000000000000000000000
--- a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/StoredImportedPlans.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package de.latlon.xplanbox.validator.storage;
-
-import java.util.Date;
-import java.util.List;
-
-/**
- * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
- * @since 8.0
- */
-public class StoredImportedPlans {
-
-	private final String linkToPlansMetadata;
-
-	private final List<String> planIds;
-
-	private final Date expirationTime;
-
-	public StoredImportedPlans(String linkToPlansMetadata, List<String> planIds) {
-		this(linkToPlansMetadata, planIds, null);
-	}
-
-	public StoredImportedPlans(String linkToPlansMetadata, List<String> planIds, Date expirationTime) {
-		this.linkToPlansMetadata = linkToPlansMetadata;
-		this.planIds = planIds;
-		this.expirationTime = expirationTime;
-	}
-
-	/**
-	 * @return the url the file can be accessed, never <code>null</code>
-	 */
-	public String getLinkToPlansMetadata() {
-		return linkToPlansMetadata;
-	}
-
-	/**
-	 * @return the date the objet expires, may be <code>null</code> if the file does not
-	 * expire
-	 */
-	public Date getExpirationTime() {
-		return expirationTime;
-	}
-
-	public List<String> getPlanIds() {
-		return planIds;
-	}
-
-}
diff --git a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/ValidationExecutionStorage.java b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/ValidationExecutionStorage.java
index a43e5f180877bc89f97f691c00f8e2d0ccb0e061..ee8cc135d502e3d46b63913f5f67cc587ff06add 100644
--- a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/ValidationExecutionStorage.java
+++ b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/ValidationExecutionStorage.java
@@ -1,8 +1,6 @@
 package de.latlon.xplanbox.validator.storage;
 
-import static de.latlon.xplanbox.validator.storage.StatusType.IMPORT_FAILED;
 import static de.latlon.xplanbox.validator.storage.StatusType.VALIDATION_FAILED;
-import static de.latlon.xplanbox.validator.storage.StatusType.VALIDATION_FINISHED;
 
 import java.io.IOException;
 import java.nio.file.Path;
@@ -34,7 +32,7 @@ public abstract class ValidationExecutionStorage {
 
 	public enum FileType {
 
-		PLAN(""), DETAILS("_details.yaml"), STATUS("_status.yaml"), PLANS("_plans.yaml");
+		PLAN(""), DETAILS("_details.yaml"), STATUS("_status.yaml"), PLANS("_plans.json");
 
 		private final String suffix;
 
@@ -134,6 +132,13 @@ public abstract class ValidationExecutionStorage {
 		changeStatusType(uuid, statusType);
 	}
 
+	public void changeStatus(String uuid, StatusType statusType, String errorMsg) throws StorageException {
+		Status status = retrieveStatus(uuid);
+		status.setStatusType(statusType);
+		status.setErrorMsg(errorMsg);
+		addToStore(Key.status(uuid), APPLICATION_YAML, serialize(status));
+	}
+
 	public void changeStatus(String uuid, String errorMsg, ErrorType errorType, StatusType statusType)
 			throws StorageException {
 		Status status = retrieveStatus(uuid);
@@ -155,15 +160,11 @@ public abstract class ValidationExecutionStorage {
 		addToStore(Key.status(uuid), APPLICATION_YAML, serialize(status));
 	}
 
-	public void changeStatus(String uuid, StatusType statusType, StoredImportedPlans storedImportedPlans)
+	public void changeStatus(String uuid, StatusType statusType, List<Integer> importedPlanIds)
 			throws StorageException {
 		Status status = retrieveStatus(uuid);
 		status.setStatusType(statusType);
-		if (storedImportedPlans != null) {
-			status.setPlanInfoLink(storedImportedPlans.getLinkToPlansMetadata());
-			status.setReportLinkExpirationTime(storedImportedPlans.getExpirationTime());
-			status.setImportedPlanIds(storedImportedPlans.getPlanIds());
-		}
+		status.setImportedPlanIds(importedPlanIds);
 		addToStore(Key.status(uuid), APPLICATION_YAML, serialize(status));
 	}
 
@@ -180,15 +181,6 @@ public abstract class ValidationExecutionStorage {
 		return retrieveContent(Key.report(uuid, reportType));
 	}
 
-	public byte[] retrievePlanInfo(String uuid) throws StorageException, EventExecutionException {
-		Status status = retrieveStatus(uuid);
-		if (status.getStatusType() == VALIDATION_FINISHED)
-			return null;
-		if (status.getStatusType() == IMPORT_FAILED || status.getStatusType() == VALIDATION_FAILED)
-			throw new EventExecutionException(status.getErrorMsg(), status.getErrorType());
-		return retrieveContent(Key.plans(uuid));
-	}
-
 	/**
 	 * @param key of the file to return, never <code>null</code>
 	 * @return the content of the file, never <code>null</code>
@@ -217,14 +209,6 @@ public abstract class ValidationExecutionStorage {
 	public abstract StoredValidationReport saveValidationResult(String uuid, Map<ReportType, Path> reports)
 			throws IOException, StorageException;
 
-	/**
-	 * ugly name to improve
-	 * @return
-	 * @throws IOException
-	 */
-	public abstract StoredImportedPlans savePlanInfo(String uuid, Path planInfo, List<String> planIds)
-			throws IOException, StorageException;
-
 	private ValidationDetails createValidationDetails(Path plan) throws IOException {
 		ValidationDetails validationDetails = new ValidationDetails();
 		if (isZipFile(plan)) {
diff --git a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/config/AmazonS3Context.java b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/config/AmazonS3ValidationContext.java
similarity index 59%
rename from xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/config/AmazonS3Context.java
rename to xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/config/AmazonS3ValidationContext.java
index 696ee17de00f4f559e355ddfa328dd5cef3596c9..49654bc37ea58b9c42a2c26755f0e83ba294a20a 100644
--- a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/config/AmazonS3Context.java
+++ b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/config/AmazonS3ValidationContext.java
@@ -20,20 +20,16 @@
  */
 package de.latlon.xplanbox.validator.storage.config;
 
-import com.amazonaws.auth.AWSCredentials;
-import com.amazonaws.auth.AWSStaticCredentialsProvider;
-import com.amazonaws.auth.BasicAWSCredentials;
-import com.amazonaws.client.builder.AwsClientBuilder;
 import com.amazonaws.services.s3.AmazonS3;
-import com.amazonaws.services.s3.AmazonS3ClientBuilder;
 import de.latlon.xplan.commons.s3.S3Storage;
 import de.latlon.xplan.commons.s3.StorageException;
+import de.latlon.xplan.commons.s3.config.AmazonS3ReadOnlyContext;
 import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
 import de.latlon.xplanbox.validator.storage.s3.S3PlanValidationExecutionStorage;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Profile;
+import org.springframework.context.annotation.Import;
 
 /**
  * Spring configuration for using AWS S3 as a storage.
@@ -43,38 +39,8 @@ import org.springframework.context.annotation.Profile;
  * @since 7.0
  */
 @Configuration
-public class AmazonS3Context {
-
-	@Bean(destroyMethod = "shutdown")
-	@Profile("!test")
-	public AmazonS3 s3Client(AWSCredentials credentials, @Value("${xplanbox.s3.region}") String signingRegion,
-			@Value("${xplanbox.s3.endpoint.url}") String endpointUrl) {
-		AmazonS3 client;
-		// TODO refactoring if/else to @ConditionalOnExpression with SpringBoot into 2
-		// SpringBeans
-		if (endpointUrl == null || endpointUrl.isEmpty()) {
-			client = AmazonS3ClientBuilder.standard()
-				.withCredentials(new AWSStaticCredentialsProvider(credentials))
-				.withRegion(signingRegion)
-				.build();
-		}
-		else {
-			AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration(endpointUrl,
-					signingRegion);
-			client = AmazonS3ClientBuilder.standard()
-				.withCredentials(new AWSStaticCredentialsProvider(credentials))
-				.withEndpointConfiguration(endpoint)
-				.build();
-		}
-		return client;
-	}
-
-	@Bean
-	@Profile("!test")
-	public AWSCredentials credentials(@Value("${xplanbox.s3.accessKeyId}") String accessKeyId,
-			@Value("${xplanbox.s3.secretKey}") String secretKey) {
-		return new BasicAWSCredentials(accessKeyId, secretKey);
-	}
+@Import(AmazonS3ReadOnlyContext.class)
+public class AmazonS3ValidationContext {
 
 	@Bean
 	public ValidationExecutionStorage validationExecutionStorage(S3Storage s3Storage,
diff --git a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/filesystem/FileSystemValidationExecutionStorage.java b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/filesystem/FileSystemValidationExecutionStorage.java
deleted file mode 100644
index 6aa7088fa7556376b79d02172498f476d7b82241..0000000000000000000000000000000000000000
--- a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/filesystem/FileSystemValidationExecutionStorage.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package de.latlon.xplanbox.validator.storage.filesystem;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
-
-import de.latlon.xplan.commons.s3.StorageException;
-import de.latlon.xplanbox.validator.storage.StoredImportedPlans;
-import de.latlon.xplanbox.validator.storage.StoredValidationReport;
-import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
-
-/**
- * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
- * @since 8.0
- */
-public class FileSystemValidationExecutionStorage extends ValidationExecutionStorage {
-
-	private final Path storageDir;
-
-	public FileSystemValidationExecutionStorage(Optional<Path> storageDir) throws IOException {
-		if (!storageDir.isPresent())
-			this.storageDir = Files.createTempDirectory("FileSystemPlanStorage");
-		else
-			this.storageDir = storageDir.get();
-		if (!Files.exists(this.storageDir))
-			Files.createDirectories(this.storageDir);
-	}
-
-	@Override
-	protected byte[] retrieveContent(Key key) throws StorageException {
-		try {
-			Path source = storageDir.resolve(key.toFileName());
-			if (!Files.exists(source))
-				throw new StorageException("File " + source + " does not exist.", 404);
-			return Files.readAllBytes(source);
-		}
-		catch (IOException e) {
-			throw new StorageException("Could not find file " + key.toFileName() + " from " + storageDir, e);
-		}
-	}
-
-	@Override
-	protected void addToStore(Key key, String contentType, byte[] content) throws StorageException {
-		Path target = storageDir.resolve(key.toFileName());
-		try {
-			Files.write(target, content);
-		}
-		catch (IOException e) {
-			throw new StorageException("Could not write file " + key.toFileName() + " to " + storageDir, e);
-		}
-	}
-
-	@Override
-	protected void addToStore(Key key, Path file) throws IOException {
-		Path target = storageDir.resolve(key.toFileName());
-		Files.copy(file, target);
-	}
-
-	@Override
-	protected void removeFromStore(Key key) throws StorageException {
-		try {
-			Path fileToDelete = storageDir.resolve(key.toFileName());
-			Files.delete(fileToDelete);
-		}
-		catch (IOException e) {
-			throw new StorageException("Could not delete file " + key.toFileName(), e);
-		}
-	}
-
-	@Override
-	public void writePlanToValidate(String uuid, Path toPath) throws IOException {
-		Path origin = storageDir.resolve(Key.plan(uuid).toFileName());
-		Files.copy(origin, toPath);
-	}
-
-	@Override
-	public StoredValidationReport saveValidationResult(String uuid, Map<ReportType, Path> reports) throws IOException {
-
-		for (Entry<ReportType, Path> entry : reports.entrySet()) {
-			Key key = Key.report(uuid, entry.getKey());
-			addToStore(key, entry.getValue());
-		}
-		return new StoredValidationReport(Key.report(uuid, ReportType.JSON).toFileName(),
-				Key.report(uuid, ReportType.PDF).toFileName());
-	}
-
-	@Override
-	public StoredImportedPlans savePlanInfo(String uuid, Path planInfo, List<String> planIds) throws IOException {
-		Key key = Key.plans(uuid);
-		addToStore(key, planInfo);
-		return new StoredImportedPlans(key.toFileName(), planIds);
-	}
-
-}
diff --git a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/s3/S3PlanValidationExecutionStorage.java b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/s3/S3PlanValidationExecutionStorage.java
index 6792557930536ec730b025a525ed96e4cb36953f..897e2458e14efbbbb5d1ffd881c57e99030c3ce5 100644
--- a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/s3/S3PlanValidationExecutionStorage.java
+++ b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/s3/S3PlanValidationExecutionStorage.java
@@ -4,7 +4,6 @@ import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
@@ -14,7 +13,6 @@ import de.latlon.xplan.commons.s3.S3Metadata;
 import de.latlon.xplan.commons.s3.S3Object;
 import de.latlon.xplan.commons.s3.S3Storage;
 import de.latlon.xplan.commons.s3.StorageException;
-import de.latlon.xplanbox.validator.storage.StoredImportedPlans;
 import de.latlon.xplanbox.validator.storage.StoredValidationReport;
 import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
 
@@ -83,13 +81,4 @@ public class S3PlanValidationExecutionStorage extends ValidationExecutionStorage
 		return new StoredValidationReport(reportLinkToJson, reportLinkToPdf, lastPutObjectResult.getExpirationTime());
 	}
 
-	@Override
-	public StoredImportedPlans savePlanInfo(String uuid, Path planInfo, List<String> planIds) throws StorageException {
-		Key key = Key.plans(uuid);
-		addToStore(key, planInfo);
-		PutObjectResult insertObject = s3Storage.insertObject(key.toFileName(), planInfo);
-		String planInfoLinkToJson = s3PublicUrl + "/" + key.toFileName();
-		return new StoredImportedPlans(planInfoLinkToJson, planIds, insertObject.getExpirationTime());
-	}
-
 }
\ No newline at end of file
diff --git a/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/filesystem/FileSystemValidationExecutionStorageStorageTest.java b/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/filesystem/FileSystemValidationExecutionStorageStorageTest.java
deleted file mode 100644
index add25365869ebc122e44f8ff28eeb4e3e0d5e345..0000000000000000000000000000000000000000
--- a/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/filesystem/FileSystemValidationExecutionStorageStorageTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package de.latlon.xplanbox.validator.storage.filesystem;
-
-import static de.latlon.xplanbox.validator.storage.StatusType.VALIDATION_REQUESTED;
-import static de.latlon.xplanbox.validator.storage.ValidationExecutionStorage.FileType.DETAILS;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Optional;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
-import de.latlon.xplan.commons.s3.StorageException;
-import de.latlon.xplanbox.validator.storage.ValidationDetails;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-
-/**
- * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
- * @since 8.0
- */
-public class FileSystemValidationExecutionStorageStorageTest {
-
-	@TempDir
-	static Path tempFolder;
-
-	@Test
-	void testAddPlan_gml() throws IOException, URISyntaxException, StorageException {
-		Path targetFolder = tempFolder.resolve("testGml");
-		Files.createDirectory(targetFolder);
-		FileSystemValidationExecutionStorage fileSystemPlanStorage = new FileSystemValidationExecutionStorage(
-				Optional.of(targetFolder));
-		URL xplanGml = getClass().getResource("/xplan.gml");
-		String key = fileSystemPlanStorage.addPlanToValidate(Paths.get(xplanGml.toURI()), VALIDATION_REQUESTED);
-
-		assertThat(Files.exists(targetFolder.resolve(key)));
-		assertThat(Files.exists(targetFolder.resolve(key + DETAILS.getSuffix())));
-
-		ValidationDetails validationDetails = deserializeDetails(targetFolder, key);
-		assertThat(validationDetails.getAttachments()).containsExactlyInAnyOrder("xplan.gml");
-	}
-
-	@Test
-	void testAddPlan_zip() throws IOException, URISyntaxException, StorageException {
-		Path targetFolder = tempFolder.resolve("testZip");
-		Files.createDirectory(targetFolder);
-		FileSystemValidationExecutionStorage fileSystemPlanStorage = new FileSystemValidationExecutionStorage(
-				Optional.of(targetFolder));
-		URL xplanGml = getClass().getResource("/BPlan002_5-3.zip");
-		String key = fileSystemPlanStorage.addPlanToValidate(Paths.get(xplanGml.toURI()), VALIDATION_REQUESTED);
-
-		assertTrue(Files.exists(targetFolder.resolve(key)));
-		assertTrue(Files.exists(targetFolder.resolve(key + DETAILS.getSuffix())));
-
-		ValidationDetails validationDetails = deserializeDetails(targetFolder, key);
-		assertThat(validationDetails.getAttachments()).containsExactlyInAnyOrder("BPlan002_5-3.pgw", "BPlan002_5-3.png",
-				"xplan.gml");
-	}
-
-	private ValidationDetails deserializeDetails(Path targetFolder, String key) throws IOException {
-		Path details = targetFolder.resolve(key + DETAILS.getSuffix());
-		byte[] detailsContent = Files.readAllBytes(details);
-		return deserialize(detailsContent);
-	}
-
-	private ValidationDetails deserialize(byte[] detailsContent) throws IOException {
-		ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
-		return mapper.readValue(detailsContent, ValidationDetails.class);
-	}
-
-}
diff --git a/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/S3ValidationExecutionStorageIT.java b/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/S3ValidationExecutionStorageIT.java
index 132fbdb13f86039391765a7944954221916be923..640d453503b6b237bcafd713b6fbc5baef74d4ef 100644
--- a/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/S3ValidationExecutionStorageIT.java
+++ b/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/S3ValidationExecutionStorageIT.java
@@ -16,7 +16,7 @@ import de.latlon.xplan.commons.s3.StorageException;
 import de.latlon.xplanbox.validator.storage.Status;
 import de.latlon.xplanbox.validator.storage.StoredValidationReport;
 import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
-import de.latlon.xplanbox.validator.storage.config.AmazonS3Context;
+import de.latlon.xplanbox.validator.storage.config.AmazonS3ValidationContext;
 import de.latlon.xplanbox.validator.storage.exception.ErrorType;
 import de.latlon.xplanbox.validator.storage.exception.EventExecutionException;
 import org.junit.jupiter.api.Assertions;
@@ -33,7 +33,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
  * @since 8.0
  */
 @ExtendWith(SpringExtension.class)
-@ContextConfiguration(classes = { AmazonS3Context.class, AmazonS3TestContext.class })
+@ContextConfiguration(classes = { AmazonS3ValidationContext.class, AmazonS3TestContext.class })
 @ActiveProfiles({ "mock" })
 @TestPropertySource("classpath:s3Mock.properties")
 public class S3ValidationExecutionStorageIT {
diff --git a/xplan-validator/xplan-validator-web/.trivyignore b/xplan-validator/xplan-validator-web/.trivyignore
index 2dc14d2ae94943b5c912d9d13d4cfb81aede38ce..27f090b2295c24a454884971c9890535b0b8e225 100644
--- a/xplan-validator/xplan-validator-web/.trivyignore
+++ b/xplan-validator/xplan-validator-web/.trivyignore
@@ -1,2 +1 @@
-# fixed in Spring 6.0.0
-CVE-2016-1000027
+# no issue to ignore currently
diff --git a/xplan-webservices/xplan-webservices-core/pom.xml b/xplan-webservices/xplan-webservices-core/pom.xml
index 66285b197ab746bb4213ec041b4f32946b215611..5f3553a0923f1ed64587de2c26159ebdc9ed2ee0 100644
--- a/xplan-webservices/xplan-webservices-core/pom.xml
+++ b/xplan-webservices/xplan-webservices-core/pom.xml
@@ -115,8 +115,8 @@
       <artifactId>jaxb-impl</artifactId>
     </dependency>
     <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>
diff --git a/xplan-webservices/xplan-webservices-core/src/test/java/de/latlon/xplan/NowTest.java b/xplan-webservices/xplan-webservices-core/src/test/java/de/latlon/xplan/NowTest.java
index 0d5c730b2c96055b8b1c1bef94b71580fd6818a4..e038f24165f3c86497a2791b566879e6040edc08 100644
--- a/xplan-webservices/xplan-webservices-core/src/test/java/de/latlon/xplan/NowTest.java
+++ b/xplan-webservices/xplan-webservices-core/src/test/java/de/latlon/xplan/NowTest.java
@@ -8,21 +8,20 @@
  * 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%
  */
 package de.latlon.xplan;
 
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.Collections;
 import java.util.Date;
@@ -32,34 +31,33 @@ import org.deegree.commons.tom.primitive.BaseType;
 import org.deegree.commons.tom.primitive.PrimitiveValue;
 import org.deegree.filter.Expression;
 import org.deegree.filter.expression.Function;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz</a>
- * @version $Revision: $, $Date: $
  */
-public class NowTest {
+class NowTest {
 
 	private final Now now = new Now();
 
 	@Test
-	public void testCreateShouldHaveCorrectName() throws Exception {
+	void testCreateShouldHaveCorrectName() throws Exception {
 		Function create = now.create(Collections.<Expression>emptyList());
 
-		assertThat(create.getName(), is(Now.NAME));
+		assertEquals(Now.NAME, create.getName());
 	}
 
 	@Test
-	public void testCreateShouldReturnCurrentDate() throws Exception {
+	void testCreateShouldReturnCurrentDate() throws Exception {
 		Date before = createDateAndSleep();
 		Function create = now.create(Collections.<Expression>emptyList());
 
 		TypedObjectNode[] evaluate = create.evaluate(Collections.<TypedObjectNode[]>emptyList());
 
-		assertThat(evaluate.length, is(1));
+		assertEquals(1, evaluate.length);
 
 		PrimitiveValue primitiveValue = (PrimitiveValue) evaluate[0];
-		assertThat(primitiveValue.getType().getBaseType(), is(BaseType.DATE_TIME));
+		assertEquals(BaseType.DATE_TIME, primitiveValue.getType().getBaseType());
 
 		Date nowDate = Now.DATE_FORMAT.parse(primitiveValue.getValue().toString());
 
diff --git a/xplan-webservices/xplan-webservices-inspireplu/.trivyignore b/xplan-webservices/xplan-webservices-inspireplu/.trivyignore
index 1578d61edc00881c44356aaf1af5e3569b38459f..27f090b2295c24a454884971c9890535b0b8e225 100644
--- a/xplan-webservices/xplan-webservices-inspireplu/.trivyignore
+++ b/xplan-webservices/xplan-webservices-inspireplu/.trivyignore
@@ -1 +1 @@
-# no issue to ignore currenty
+# no issue to ignore currently
diff --git a/xplan-webservices/xplan-webservices-mapproxy/xplan-mapproxy-docker/.trivyignore b/xplan-webservices/xplan-webservices-mapproxy/xplan-mapproxy-docker/.trivyignore
index 1578d61edc00881c44356aaf1af5e3569b38459f..27f090b2295c24a454884971c9890535b0b8e225 100644
--- a/xplan-webservices/xplan-webservices-mapproxy/xplan-mapproxy-docker/.trivyignore
+++ b/xplan-webservices/xplan-webservices-mapproxy/xplan-mapproxy-docker/.trivyignore
@@ -1 +1 @@
-# no issue to ignore currenty
+# no issue to ignore currently
diff --git a/xplan-webservices/xplan-webservices-mapproxy/xplan-mapproxy-docker/Dockerfile b/xplan-webservices/xplan-webservices-mapproxy/xplan-mapproxy-docker/Dockerfile
index e7004c66c837352e7f9e305693a98b93e46a2b05..efb771f21c42406825707dc20c7ef46a3cd998fa 100644
--- a/xplan-webservices/xplan-webservices-mapproxy/xplan-mapproxy-docker/Dockerfile
+++ b/xplan-webservices/xplan-webservices-mapproxy/xplan-mapproxy-docker/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.10.13-slim
+FROM python:3.12-slim
 
 ARG MAPPROXY_VERSION=1.16.0
 ARG BUILD_DATE=?
@@ -40,7 +40,7 @@ RUN apt update && apt -y install --no-install-recommends \
     apt-get clean && \
     rm -rf /var/lib/apt/lists/* && \
     python -m venv --system-site-packages /srv/mapproxy/venv && \
-    pip install mapproxy==$MAPPROXY_VERSION uwsgi pyproj pillow pyyaml boto3 shapely==1.7.1 && \
+    pip install mapproxy==$MAPPROXY_VERSION uwsgi pyproj pillow pyyaml boto3 shapely==1.7.1 setuptools && \
     pip cache purge && \
     addgroup --gid 1001 mapproxy && \
     adduser --uid 1001 --shell /bin/false --gid 1001 --no-create-home --disabled-login mapproxy && \
diff --git a/xplan-webservices/xplan-webservices-validator-wms/.trivyignore b/xplan-webservices/xplan-webservices-validator-wms/.trivyignore
index 1578d61edc00881c44356aaf1af5e3569b38459f..27f090b2295c24a454884971c9890535b0b8e225 100644
--- a/xplan-webservices/xplan-webservices-validator-wms/.trivyignore
+++ b/xplan-webservices/xplan-webservices-validator-wms/.trivyignore
@@ -1 +1 @@
-# no issue to ignore currenty
+# no issue to ignore currently
diff --git a/xplan-webservices/xplan-webservices-workspaces/src/main/workspace/themes/fplanraster.xml b/xplan-webservices/xplan-webservices-workspaces/src/main/workspace/themes/fplanraster.xml
index a12b341d06f1d4321732d88c70895a46b679b0fa..c9f132a65a1f29bbcd9ee2f09f1442a34eaf6fa6 100644
--- a/xplan-webservices/xplan-webservices-workspaces/src/main/workspace/themes/fplanraster.xml
+++ b/xplan-webservices/xplan-webservices-workspaces/src/main/workspace/themes/fplanraster.xml
@@ -29,7 +29,7 @@
     <Theme>
       <Identifier>fplanraster_sortiert</Identifier>
       <d:Title>FP Raster Theme</d:Title>
-      <!--<Layer layerStore="mapserver">fp_raster</Layer>-->
+      <Layer layerStore="mapserver">fp_raster</Layer>
     </Theme>
   </Theme>
 </Themes>