From 5476e4bceef31d51378abef49bc1bbbc0e8927a3 Mon Sep 17 00:00:00 2001
From: latlon team <info@lat-lon.de>
Date: Mon, 12 Aug 2024 05:54:55 +0000
Subject: [PATCH] Code drop

- XPLANBOX-3161 update docker-maven-plugin to 0.45.0, fix 2x dependency (0d14a3b57)
- XPLANBOX-3169 - disabled assertions of status tests (195ab596c)
- XPLANBOX-2765 - enhanced xxplan-manager-api application.properties (e56ec22ad)
- XPLANBOX-2765 - improved readme, fixed formatting (c9fd908e1)
- XPLANBOX-3169 - improved assertions of FINISHED test (0403eccfb)
- XPLANBOX-2765 - send public events at start & end of validation (eef02bb6a)
- XPLANBOX-3171 - Modify variable baseUrlValidatorApi to not expect content path (f3b6898f7)
- XPLANBOX-3169 - Make Groovy test steps fail after 20 attempts and deactivate failing test steps (1e0e8498c)
- Revert "XPLANBOX-3113 - Removed basic authentication of v2 openAPI and showConfig test cases" (358f0fe06)
- XPLANBOX-3170 - Remove HTTP status code 422 from XPlanValidatorAPI version 2 (1a0332347)
- XPLANBOX-3169 - Implement SoapUI test for status FAILED (f76db4e4c)
- XPLANBOX-3113 - Removed basic authentication of v2 openAPI and showConfig test cases (48ade652d)
- XPLANBOX-3113 - Added basic authorization for v2 testcases (913a4fe17)
- XPLANBOX-3153 - status instead of validation result in ValidationFinishedEvent (88fc95234)
- XPLANBOX-3131 - exception handling v2 (6279de9b9)
- XPLANBOX-3113 - Fixed two assertions (ed4d113f0)
- XPLANBOX-3158 - access to xplan-validator-workspace in xplan-validator-executor (98f4e9dff)
- XPLANBOX-3113 - Updated and unified naming of expected error testcases (521b1071c)
- XPLANBOX-2756 don't process plans concurrently (d1fa67237)
- XPLANBOX-3122 unit test & fix (e375073f4)
- XPLANBOX-3113 - Updated and unified naming of expected error testcases (b66cafd32)
- XPLANBOX-3144 - replaced endpoint with baseUrlValidatorApi after changes in soapui project (388ae6844)
- XPLANBOX-3122 - removed ValidationHandler (moved to xplan-validator-executor), moved ValidationHandlerTest to xplan-validator-executor (54949480b)
- XPLANBOX-3153 - described exceptions in /status/{uuid}, handle 404 (7671dc74d)
- XPLANBOX-3113 - added soapui test /status/{uuid} -> GET BP 6.0.2 XX retrieveStatus invalidAcceptHeader expectError (bb7a8189b)
- XPLANBOX-3149 - fixed formatting (77dec47c9)
- XPLANBOX-3149 add validation unit tests previously in validation-api (29111a229)
- XPLANBOX-3150 remove s3mock shutdown & fix renaming of s3.* properties (ca23b7c43)
- fix unit test (4b99a7348)
- XPLANBOX-3113 - Set descriptions in SoapUI tests for XPlanValidatorAPI version 2 (edb0018bf)
- XPLANBOX-3113 - Implement SoapUI tests for XPlanValidatorAPI version 2 (9f6e0d23b)
- XPLANBOX-3143 - Remove @Hidden from /status path (344fe4f96)
- XPLANBOX-3141 - fixed property name; fixed links (a38558b9e)
- XPLANBOX-3114 fix env property name (d3d68f799)
- XPLANBOX-3141 move configuration to application properties (8af7d8aaa)
- XPLANBOX-3118 remove rabbit profile (80495c1c2)
- XPLANBOX-2762 - restored dependencies to regeln (otherwise they are missin in /info) (ce9e50cd8)
- XPLANBOX-2762 - fixed xml, zip and pdf response (c887857c4)
- XPLANBOX-2762 - added ValidationTimeout exception (91420603c)
- XPLANBOX-2762 - added de.xleitstelle.xplanung.regeln to xplan-validator-executor; removed regeln and profile dependencies from xplan-validator-api (2df6fea82)
- XPLANBOX-2762 v1 validation starts wrapping async validation, cleanup (0df0273d4)
- XPLANBOX-3121 - added link to pdf report (d870f375e)
- XPLANBOX-2847 - implemented removed files afte validation; added missing pom (6ec852418)
- XPLANBOX-2847 - enhanced link to report, added IT (70282a255)
- XPLANBOX-2847 - set expiration days for bucket XPLAN_S3_BUCKET_NAME_EXECUTION, return expiration date for validation report (8679e9e6f)
- XPLANBOX-3115 - added links; fixed tests; fixes s3 implementation (f841b2e25)
- XPLANBOX-3115 - implemented /v2/status/{uuid} (8344523d1)
- XPLANBOX-2758 - added spring-boot-starter-actuator and enabled health.probes (e325d84a2)
- XPLANBOX-2758 - added modules xplan-validator-storage and xplan-validator-executor (2b0f5f69f)
- XPLANBOX-2761 - fixed/enabled unit test by adding getContextId (c51061fb6)
- XPLANBOX-2759 - implemented /v2/validate with GML (f2176dd0f)
- XPLANBOX-2761 - seperated ResourceConfigs to fix mixing OpenAPI documents (553fc1b61)
- XPLANBOX-2756 - implemented XPlanValidatorAPI v2 (1ca148f5d)
- XPLANBOX-2760 - renamed PlanStorage and profile; added variable to set directory; implemented required methods in S3PlanValidationExecutionStorage (241972135)
- XPLANBOX-2761/2759 - receive validation request event, validate & send validation ready (2e7acfcba)
- XPLANBOX-2761 - api v2, send event, consume event (bfe02763d)
- XPLANBOX-2756 - WIP - store XPlanArchive in S3 or filesystem (fac7c26ef)

Co-authored-by: Dirk Stenger <stenger@lat-lon.de>
Co-authored-by: Julian Zilz <zilz@lat-lon.de>
Co-authored-by: Lyn Elisa Goltz <goltz@lat-lon.de>
Co-authored-by: Marc Guillemot <guillemot@lat-lon.de>

Dropped from commit: d9d8dd45563c252aa396eb40bedb99d8eb42c406
---
 jenkinsfiles/test.Jenkinsfile                 |    8 +-
 pom.xml                                       |   13 +-
 .../api/commons/openapi/OpenApiFilter.java    |    2 +-
 .../api/commons/v1/model/AbstractLink.java    |  163 ++
 xplan-core/xplan-core-commons/pom.xml         |    4 +
 .../latlon/xplan/commons}/s3/S3Metadata.java  |    2 +-
 .../de/latlon/xplan/commons}/s3/S3Object.java |    2 +-
 .../latlon/xplan/commons}/s3/S3Storage.java   |   48 +-
 .../xplan/commons/s3}/StorageException.java   |    7 +-
 xplan-core/xplan-core-manager/pom.xml         |    1 -
 .../manager/document/DocumentStorage.java     |    2 +-
 .../document/XPlanDocumentManager.java        |    2 +-
 .../document/s3/S3DocumentStorage.java        |    6 +-
 .../AmazonS3DocumentStorageContext.java       |    2 +-
 .../storage/StorageCleanUpManager.java        |    2 +-
 .../xplan/manager/storage/StorageEvent.java   |    2 +-
 .../FilesystemStorageCleanUpManager.java      |    2 +-
 .../storage/s3/S3StorageCleanUpManager.java   |    4 +-
 .../storage/s3/config/AmazonS3Context.java    |   15 +-
 .../s3/listener/S3TransactionListener.java    |    6 +-
 .../service/XPlanDeleteService.java           |    2 +-
 .../transaction/service/XPlanEditService.java |    2 +-
 .../service/XPlanInsertService.java           |    2 +-
 .../wmsconfig/raster/XPlanRasterManager.java  |    2 +-
 .../raster/storage/RasterStorage.java         |    1 +
 .../raster/storage/s3/S3RasterStorage.java    |    7 +-
 .../config/AmazonS3RasterStorageContext.java  |    2 +-
 .../document/s3/S3DocumentStorageIT.java      |    2 +-
 .../s3/S3StorageCleanUpManagerTest.java       |    6 +-
 .../storage/s3/S3StorageTestManual.java       |    5 +-
 .../s3/config/AmazonS3TestContext.java        |   11 +-
 .../s3/config/S3StorageTestContext.java       |    4 +-
 .../storage/s3/S3RasterStorageTest.java       |   43 +-
 .../storage/s3/S3RasterStorageTestManual.java |    4 +-
 .../src/test/resources/s3Mock.properties      |   10 +-
 ...nRequestNotifier.java => EventSender.java} |   12 +-
 .../core/validator/events/RabbitConfig.java   |   57 +-
 .../validator/events/RabbitEmitterConfig.java |   39 +-
 .../validator/events/RabbitEventSender.java   |   81 +
 .../events/RabbitReceiverConfig.java          |   41 +-
 .../core/validator/events/RabbitSettings.java |   32 +-
 .../events/ValidationFinishedEvent.java       |   62 +
 .../events/ValidationRequestedEvent.java      |   74 +-
 .../events/ValidationTaskQueueConfig.java     |   13 +
 .../events/XPlanboxInternalEvent.java         |   11 +
 .../events/XPlanboxInternalFanoutEvent.java   |   11 +
 .../events/XPlanboxInternalTaskEvent.java     |   11 +
 .../validator/events/XPlanboxPublicEvent.java |   11 +
 .../events/v1/XPlanboxPublicV1Event.java      |   78 +
 .../events/ValidationFinishedEventTest.java}  |   29 +-
 .../events/ValidationRequestedEventTest.java  |    5 +-
 .../events/v1/XPlanboxPublicV1EventTest.java  |   39 +
 .../xplan-docker-volume-init/setupVolumes.sh  |    2 -
 .../src/main/asciidoc/s3storage.adoc          |    2 -
 .../dokumente/config/S3DocumentContext.java   |    4 +-
 .../dokumente/handler/DocumentHandler.java    |    3 +-
 .../dokumente/service/DocumentService.java    |    2 +-
 .../service/s3/S3DocumentService.java         |    8 +-
 .../xplanbox/api/manager/PlanInfoBuilder.java |   33 +-
 .../xplanbox/api/manager/v1/model/Link.java   |  153 +-
 .../src/main/resources/application.properties |   13 +
 xplan-manager/xplan-manager-web/pom.xml       |    5 -
 xplan-tests/xplan-tests-selenium/README.md    |    9 +-
 xplan-tests/xplan-tests-selenium/pom.xml      |   27 +-
 .../runAllSeleniumTests.sh                    |    1 +
 .../rabbit/ValidationPublicEventsIT.java      |  219 +++
 .../validator/rabbit/ValidatorApiV2.java      |   33 +
 xplan-tests/xplan-tests-soapui/README.md      |    2 +-
 xplan-tests/xplan-tests-soapui/pom.xml        |    6 +-
 .../xplan-tests-soapui/runAllSoapUiTests.sh   |    2 +-
 .../xplan-validator-api-soapui-project.xml    | 1234 ++++++++++--
 xplan-validator/pom.xml                       |    2 +
 .../xplan-validator-api/Dockerfile            |    5 +-
 xplan-validator/xplan-validator-api/README.md |   22 +-
 xplan-validator/xplan-validator-api/pom.xml   |   10 +-
 .../xplanbox/api/validator/SpringBootApp.java |   40 +-
 .../AbstractApiConfig.java}                   |   99 +-
 .../api/validator/api/v1/ApiV1Config.java     |   78 +
 .../api/validator/api/v2/ApiV2Config.java     |   81 +
 .../api/validator/api/v2/ApiV2Filter.java     |   22 +
 .../validator/config/ApplicationContext.java  |   37 +-
 .../validator/config/RabbitConfiguration.java |    3 +-
 .../exception/InvalidValidationUuid.java      |   44 +
 .../ValidationExecutionExceptionMapper.java   |   44 +
 .../exception/ValidationTimeout.java          |   44 +
 .../handler/AsyncValidationWrapper.java       |  102 +
 .../xplanbox/api/validator/v1/DefaultApi.java |   16 +-
 .../xplanbox/api/validator/v1/InfoApi.java    |    2 +
 .../api/validator/v1/ValidateApi.java         |  158 +-
 .../api/validator/v2/DefaultApi2.java         |   72 +
 .../xplanbox/api/validator/v2/InfoApi2.java   |   62 +
 .../xplanbox/api/validator/v2/StatusApi.java  |   83 +
 .../api/validator/v2/ValidateApi2.java        |  197 ++
 .../xplanbox/api/validator/v2/model/Link.java |  144 ++
 .../api/validator/v2/model/StatusEnum.java    |   21 +
 .../v2/model/StatusNotification.java          |   94 +
 .../validator/v2/model/ValidationReceipt.java |   41 +-
 .../main/resources/application-dev.properties |   23 +
 .../src/main/resources/application.properties |   13 +
 .../config/FakeAsyncValidationWrapper.java    |   51 +
 .../api/validator/config/TestContext.java     |   22 +-
 .../handler/AsyncValidationWrapperTest.java   |  136 ++
 .../validator/handler/ConfigHandlerTest.java  |    3 +-
 .../api/validator/v1/DefaultApiTest.java      |   16 +-
 .../validator/v1/ValidateApiJerseyTest.java   |  236 +++
 .../api/validator/v1/ValidateApiTest.java     |  223 +--
 .../api/validator/v2/DefaultApi2Test.java     |  139 ++
 .../api/validator/v2/InfoApi2Test.java        |   92 +
 .../api/validator/v2/StatusApi2Test.java      |   80 +
 .../api/validator/v2/ValidateApi2Test.java    |  147 ++
 .../api/validator/v1/validation-report1.json  |    1 +
 .../api/validator/v1/validation-report2.xml   |    1 +
 .../xplan-validator-executor/Dockerfile       |   44 +
 .../xplan-validator-executor/README.md        |   11 +
 .../xplan-validator-executor/pom.xml          |  217 +++
 .../xplan-validator-executor/run.sh           |   10 +
 .../validator/executor/PlanValidator.java     |  155 ++
 .../validator/executor/SpringBootApp.java     |   54 +
 .../executor/config/ApplicationContext.java   |  162 ++
 .../config/ExecutorRabbitConfiguration.java   |   31 +-
 .../executor}/handler/ValidationHandler.java  |    2 +-
 .../executor/messagingrabbitmq/Receiver.java  |   71 +
 .../main/resources/application-dev.properties |   23 +
 .../src/main/resources/application.properties |   50 +
 .../src/main/resources/log4j2.yaml            |   82 +
 .../validator/executor/PlanValidatorTest.java |  196 ++
 .../handler/ValidationHandlerTest.java        |   29 +-
 .../src/test/resources/bplan_valid_41.zip     |  Bin 0 -> 1652 bytes
 .../resources/config/application.properties   |   26 +
 .../validator/executor/report1.expected.json  | 1697 +++++++++++++++++
 .../validator/executor/report2.expected.xml   |    1 +
 .../validator/executor/report6.expected.json  |    1 +
 .../validator/executor/report7.expected.json  |    1 +
 .../src/test/resources/xplan.gml              |  100 +
 .../xplan-validator-storage/pom.xml           |   71 +
 .../xplanbox/validator/storage/ErrorType.java |   34 +
 .../xplanbox/validator/storage/Status.java    |   77 +
 .../validator/storage/StatusType.java         |   21 +
 .../storage/StoredValidationReport.java       |   46 +
 .../validator/storage/ValidationDetails.java  |   29 +
 .../storage/ValidationExecutionException.java |   20 +
 .../storage/ValidationExecutionStorage.java   |  238 +++
 .../storage/config/AmazonS3Context.java       |   92 +
 .../FileSystemValidationExecutionStorage.java |   89 +
 .../s3/S3PlanValidationExecutionStorage.java  |   84 +
 ...ValidationExecutionStorageStorageTest.java |   75 +
 .../storage/s3/AmazonS3TestContext.java       |   88 +
 .../s3/S3ValidationExecutionStorageIT.java    |   87 +
 .../s3/S3ValidationExecutionStorageTest.java  |  111 ++
 .../src/test/resources/BPlan002_5-3.zip       |  Bin 0 -> 60474 bytes
 .../src/test/resources/s3Mock.properties      |   25 +
 .../src/test/resources/xplan.gml              |  100 +
 .../xplan/validator/wms/libs.expected.txt     |    7 +
 153 files changed, 8786 insertions(+), 937 deletions(-)
 create mode 100644 xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/AbstractLink.java
 rename xplan-core/{xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage => xplan-core-commons/src/main/java/de/latlon/xplan/commons}/s3/S3Metadata.java (97%)
 rename xplan-core/{xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage => xplan-core-commons/src/main/java/de/latlon/xplan/commons}/s3/S3Object.java (96%)
 rename xplan-core/{xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage => xplan-core-commons/src/main/java/de/latlon/xplan/commons}/s3/S3Storage.java (82%)
 rename xplan-core/{xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage => xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3}/StorageException.java (89%)
 rename xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/{ValidationRequestNotifier.java => EventSender.java} (87%)
 create mode 100644 xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitEventSender.java
 create mode 100644 xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationFinishedEvent.java
 create mode 100644 xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationTaskQueueConfig.java
 create mode 100644 xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxInternalEvent.java
 create mode 100644 xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxInternalFanoutEvent.java
 create mode 100644 xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxInternalTaskEvent.java
 create mode 100644 xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxPublicEvent.java
 create mode 100644 xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/v1/XPlanboxPublicV1Event.java
 rename xplan-core/xplan-core-validator-events/src/{main/java/de/latlon/core/validator/events/RabbitValidationRequestNotifier.java => test/java/de/latlon/core/validator/events/ValidationFinishedEventTest.java} (57%)
 create mode 100644 xplan-core/xplan-core-validator-events/src/test/java/de/latlon/core/validator/events/v1/XPlanboxPublicV1EventTest.java
 create mode 100644 xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/validator/rabbit/ValidationPublicEventsIT.java
 create mode 100644 xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/validator/rabbit/ValidatorApiV2.java
 rename xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/{config/JerseyConfig.java => api/AbstractApiConfig.java} (70%)
 create mode 100644 xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/api/v1/ApiV1Config.java
 create mode 100644 xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/api/v2/ApiV2Config.java
 create mode 100644 xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/api/v2/ApiV2Filter.java
 create mode 100644 xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/exception/InvalidValidationUuid.java
 create mode 100644 xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/exception/ValidationExecutionExceptionMapper.java
 create mode 100644 xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/exception/ValidationTimeout.java
 create mode 100644 xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/handler/AsyncValidationWrapper.java
 create mode 100644 xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/DefaultApi2.java
 create mode 100644 xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/InfoApi2.java
 create mode 100644 xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/StatusApi.java
 create mode 100644 xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/ValidateApi2.java
 create mode 100644 xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/model/Link.java
 create mode 100644 xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/model/StatusEnum.java
 create mode 100644 xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/model/StatusNotification.java
 rename xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationMessageReceiver.java => xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/model/ValidationReceipt.java (57%)
 create mode 100644 xplan-validator/xplan-validator-api/src/main/resources/application-dev.properties
 create mode 100644 xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/config/FakeAsyncValidationWrapper.java
 create mode 100644 xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/handler/AsyncValidationWrapperTest.java
 create mode 100644 xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v1/ValidateApiJerseyTest.java
 create mode 100644 xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v2/DefaultApi2Test.java
 create mode 100644 xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v2/InfoApi2Test.java
 create mode 100644 xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v2/StatusApi2Test.java
 create mode 100644 xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v2/ValidateApi2Test.java
 create mode 100644 xplan-validator/xplan-validator-api/src/test/resources/de/latlon/xplanbox/api/validator/v1/validation-report1.json
 create mode 100644 xplan-validator/xplan-validator-api/src/test/resources/de/latlon/xplanbox/api/validator/v1/validation-report2.xml
 create mode 100644 xplan-validator/xplan-validator-executor/Dockerfile
 create mode 100644 xplan-validator/xplan-validator-executor/README.md
 create mode 100644 xplan-validator/xplan-validator-executor/pom.xml
 create mode 100755 xplan-validator/xplan-validator-executor/run.sh
 create mode 100644 xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/PlanValidator.java
 create mode 100644 xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/SpringBootApp.java
 create mode 100644 xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/config/ApplicationContext.java
 rename xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/messagingrabbitmq/Receiver.java => xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/config/ExecutorRabbitConfiguration.java (56%)
 rename xplan-validator/{xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator => xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor}/handler/ValidationHandler.java (99%)
 create mode 100644 xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/messagingrabbitmq/Receiver.java
 create mode 100644 xplan-validator/xplan-validator-executor/src/main/resources/application-dev.properties
 create mode 100644 xplan-validator/xplan-validator-executor/src/main/resources/application.properties
 create mode 100644 xplan-validator/xplan-validator-executor/src/main/resources/log4j2.yaml
 create mode 100644 xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/PlanValidatorTest.java
 rename xplan-validator/{xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator => xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor}/handler/ValidationHandlerTest.java (91%)
 create mode 100644 xplan-validator/xplan-validator-executor/src/test/resources/bplan_valid_41.zip
 create mode 100644 xplan-validator/xplan-validator-executor/src/test/resources/config/application.properties
 create mode 100644 xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report1.expected.json
 create mode 100644 xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report2.expected.xml
 create mode 100644 xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report6.expected.json
 create mode 100644 xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report7.expected.json
 create mode 100644 xplan-validator/xplan-validator-executor/src/test/resources/xplan.gml
 create mode 100644 xplan-validator/xplan-validator-storage/pom.xml
 create mode 100644 xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/ErrorType.java
 create mode 100644 xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/Status.java
 create mode 100644 xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/StatusType.java
 create mode 100644 xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/StoredValidationReport.java
 create mode 100644 xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/ValidationDetails.java
 create mode 100644 xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/ValidationExecutionException.java
 create mode 100644 xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/ValidationExecutionStorage.java
 create mode 100644 xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/config/AmazonS3Context.java
 create mode 100644 xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/filesystem/FileSystemValidationExecutionStorage.java
 create mode 100644 xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/s3/S3PlanValidationExecutionStorage.java
 create mode 100644 xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/filesystem/FileSystemValidationExecutionStorageStorageTest.java
 create mode 100644 xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/AmazonS3TestContext.java
 create mode 100644 xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/S3ValidationExecutionStorageIT.java
 create mode 100644 xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/S3ValidationExecutionStorageTest.java
 create mode 100644 xplan-validator/xplan-validator-storage/src/test/resources/BPlan002_5-3.zip
 create mode 100644 xplan-validator/xplan-validator-storage/src/test/resources/s3Mock.properties
 create mode 100644 xplan-validator/xplan-validator-storage/src/test/resources/xplan.gml

diff --git a/jenkinsfiles/test.Jenkinsfile b/jenkinsfiles/test.Jenkinsfile
index 783068c56f..2d06afdbe0 100644
--- a/jenkinsfiles/test.Jenkinsfile
+++ b/jenkinsfiles/test.Jenkinsfile
@@ -8,7 +8,7 @@ pipeline {
       string(name: 'BRANCH', defaultValue: "main", description: 'Set branch')
       string(name: 'CREDENTIALS_ID', defaultValue: "xplanbox.lat-lon.de", description: 'Set id of Jenkins credentials to login to environment (BASIC AUTH)')
       string(name: 'SERVICES_API_KEY', defaultValue: "xplanbox", description: 'Set ApiKey to access /config of XPlanDienste')
-      string(name: 'ENDPOINT_VALIDATOR_API', defaultValue: "https://xplanbox.lat-lon.de/xvalidator/api/v1", description: 'Set endpoint of XPlanValidatorAPI')
+      string(name: 'BASE_URL_VALIDATOR_API', defaultValue: "https://xplanbox.lat-lon.de", description: 'Set base URL of XPlanValidatorAPI')
       string(name: 'BASE_URL_DIENSTE', defaultValue: "https://xplanbox.lat-lon.de", description: 'Set base URL of XPlanDienste')
       string(name: 'BASE_URL_INSPIRE_PLU', defaultValue: "https://xplanbox.lat-lon.de", description: 'Set base URL of INSPIRE PLU')
       string(name: 'BASE_URL_MANAGER_API', defaultValue: "https://xplanbox.lat-lon.de", description: 'Set base URL of XPlanManagerAPI')
@@ -44,7 +44,7 @@ pipeline {
                usernamePassword(credentialsId:"${CREDENTIALS_ID}", passwordVariable: 'Password', usernameVariable: 'Username')
             ]) {
                sh 'mvn test -pl :xplan-tests-soapui -Psystem-tests -DtestFileName=xplan-validator-api-soapui-project.xml \
-                       -Dendpoint=${ENDPOINT_VALIDATOR_API} -Dusername=$Username -Dpassword=$Password'
+                       -DbaseUrlValidatorApi=${BASE_URL_VALIDATOR_API} -Dusername=$Username -Dpassword=$Password'
             }
          }
       }
@@ -79,7 +79,9 @@ pipeline {
             withCredentials([
                usernamePassword(credentialsId:"${CREDENTIALS_ID}", passwordVariable: 'Password', usernameVariable: 'Username')
             ]) {
-               sh 'mvn integration-test -pl :xplan-tests-selenium -Psystem-tests -DbaseUrlValidatorWeb=${BASE_URL_VALIDATOR_WEB} -Dusername=$Username -Dpassword=$Password'
+				withEnv(['SKIP_RABBIT_TESTS=true']) {
+	               sh 'mvn integration-test -pl :xplan-tests-selenium -Psystem-tests -DbaseUrlValidatorWeb=${BASE_URL_VALIDATOR_WEB} -Dusername=$Username -Dpassword=$Password'
+				}
             }
          }
       }
diff --git a/pom.xml b/pom.xml
index 47c1a68d7d..e7e52fef6a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -759,7 +759,7 @@
         <plugin>
           <groupId>io.fabric8</groupId>
           <artifactId>docker-maven-plugin</artifactId>
-          <version>0.44.0</version>
+          <version>0.45.0</version>
         </plugin>
         <plugin>
           <groupId>org.codehaus.mojo</groupId>
@@ -1095,6 +1095,11 @@
         <artifactId>xplan-core-validator-events</artifactId>
         <version>${project.version}</version>
       </dependency>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>xplan-validator-storage</artifactId>
+        <version>${project.version}</version>
+      </dependency>
       <dependency>
         <groupId>${project.groupId}</groupId>
         <artifactId>xplan-core-schemas</artifactId>
@@ -1150,6 +1155,12 @@
         <version>1.1.1</version>
         <scope>test</scope>
       </dependency>
+      <dependency>
+        <groupId>io.findify</groupId>
+        <artifactId>s3mock_2.13</artifactId>
+        <version>0.2.6</version>
+        <scope>test</scope>
+      </dependency>
       <!-- pdf report -->
       <dependency>
         <groupId>com.github.librepdf</groupId>
diff --git a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/openapi/OpenApiFilter.java b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/openapi/OpenApiFilter.java
index 9161f5a09b..1ca5b88e40 100644
--- a/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/openapi/OpenApiFilter.java
+++ b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/openapi/OpenApiFilter.java
@@ -88,7 +88,7 @@ public class OpenApiFilter extends AbstractSpecFilter {
 		paths.putAll(filteredPathItems);
 	}
 
-	private String createNewKey(String path) {
+	protected String createNewKey(String path) {
 		Pattern pattern = Pattern.compile("\\/(xvalidator|xmanager|xdokumente)\\/api\\/v[\\d_\\-\\.]*(\\/|)");
 		Matcher matcher = pattern.matcher(path);
 		return matcher.replaceFirst("/");
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
new file mode 100644
index 0000000000..29caeb95b4
--- /dev/null
+++ b/xplan-core/xplan-core-api/src/main/java/de/latlon/xplanbox/api/commons/v1/model/AbstractLink.java
@@ -0,0 +1,163 @@
+/*-
+ * #%L
+ * xplan-manager-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%
+ */
+package de.latlon.xplanbox.api.commons.v1.model;
+
+import java.net.URI;
+import java.util.Objects;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+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;
+
+/**
+ * Datatype for Link. A AbstractLink to a resource related to the resource such as
+ * XPlanWerkWMS or the resource itself.
+ *
+ * @since 4.0
+ */
+@Schema(description = "Link to a resource related to the resource such as XPlanWerkWMS or the resource itself")
+@jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaJAXRSSpecServerCodegen",
+		date = "2020-08-28T13:42:47.160+02:00[Europe/Berlin]")
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class AbstractLink {
+
+	private @Valid URI href;
+
+	private @Valid String type;
+
+	private @Valid String hreflang;
+
+	private @Valid String title;
+
+	private @Valid Integer length;
+
+	public AbstractLink href(URI href) {
+		this.href = href;
+		return this;
+	}
+
+	@Schema(example = "https://xplanbox.lat-lon.de/xmanager/api/v1/plan/123", required = true)
+	@JsonProperty("href")
+	@NotNull
+	public URI getHref() {
+		return href;
+	}
+
+	public void setHref(URI href) {
+		this.href = href;
+	}
+
+	public AbstractLink type(String type) {
+		this.type = type;
+		return this;
+	}
+
+	@Schema(example = "application/json")
+	@JsonProperty("type")
+	public String getType() {
+		return type;
+	}
+
+	public void setType(String type) {
+		this.type = type;
+	}
+
+	public AbstractLink hreflang(String hreflang) {
+		this.hreflang = hreflang;
+		return this;
+	}
+
+	@Schema(example = "en")
+	@JsonProperty("hreflang")
+	public String getHreflang() {
+		return hreflang;
+	}
+
+	public void setHreflang(String hreflang) {
+		this.hreflang = hreflang;
+	}
+
+	public AbstractLink title(String title) {
+		this.title = title;
+		return this;
+	}
+
+	@Schema(example = "Othmarschen 3, Hamburg")
+	@JsonProperty("title")
+	public String getTitle() {
+		return title;
+	}
+
+	public void setTitle(String title) {
+		this.title = title;
+	}
+
+	public AbstractLink length(Integer length) {
+		this.length = length;
+		return this;
+	}
+
+	@Schema
+	@JsonProperty("length")
+	public Integer getLength() {
+		return length;
+	}
+
+	public void setLength(Integer length) {
+		this.length = length;
+	}
+
+	@Override
+	public boolean equals(Object o) {
+		if (this == o) {
+			return true;
+		}
+		if (o == null || getClass() != o.getClass()) {
+			return false;
+		}
+		AbstractLink link = (AbstractLink) o;
+		return Objects.equals(this.href, link.href) && Objects.equals(this.type, link.type)
+				&& Objects.equals(this.hreflang, link.hreflang) && Objects.equals(this.title, link.title)
+				&& Objects.equals(this.length, link.length);
+	}
+
+	@Override
+	public int hashCode() {
+		return Objects.hash(href, type, hreflang, title, length);
+	}
+
+	/**
+	 * Convert the given object to string with each line indented by 4 spaces (except the
+	 * first line).
+	 */
+	protected String toIndentedString(Object o) {
+		if (o == null) {
+			return "null";
+		}
+		return o.toString().replace("\n", "\n    ");
+	}
+
+}
diff --git a/xplan-core/xplan-core-commons/pom.xml b/xplan-core/xplan-core-commons/pom.xml
index 44119c28e0..afda0793b6 100644
--- a/xplan-core/xplan-core-commons/pom.xml
+++ b/xplan-core/xplan-core-commons/pom.xml
@@ -120,6 +120,10 @@
       <artifactId>assertj-core</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>com.amazonaws</groupId>
+      <artifactId>aws-java-sdk-s3</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/S3Metadata.java b/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/S3Metadata.java
similarity index 97%
rename from xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/S3Metadata.java
rename to xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/S3Metadata.java
index 74d7a5dcf3..df5eccda75 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/S3Metadata.java
+++ b/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/S3Metadata.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;
+package de.latlon.xplan.commons.s3;
 
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/S3Object.java b/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/S3Object.java
similarity index 96%
rename from xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/S3Object.java
rename to xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/S3Object.java
index b9cb4d69d6..5ae595abbc 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/S3Object.java
+++ b/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/S3Object.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;
+package de.latlon.xplan.commons.s3;
 
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/S3Storage.java b/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/S3Storage.java
similarity index 82%
rename from xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/S3Storage.java
rename to xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/S3Storage.java
index 65cee68860..e16095e7c9 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/S3Storage.java
+++ b/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/S3Storage.java
@@ -18,29 +18,33 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  * #L%
  */
-package de.latlon.xplan.manager.storage.s3;
+package de.latlon.xplan.commons.s3;
+
+import static com.amazonaws.services.s3.model.BucketLifecycleConfiguration.ENABLED;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.util.List;
 
 import com.amazonaws.AmazonServiceException;
 import com.amazonaws.services.s3.AmazonS3;
 import com.amazonaws.services.s3.model.AmazonS3Exception;
 import com.amazonaws.services.s3.model.Bucket;
+import com.amazonaws.services.s3.model.BucketLifecycleConfiguration;
 import com.amazonaws.services.s3.model.ObjectListing;
 import com.amazonaws.services.s3.model.ObjectMetadata;
+import com.amazonaws.services.s3.model.PutObjectResult;
 import com.amazonaws.services.s3.model.S3Object;
 import com.amazonaws.services.s3.model.S3ObjectSummary;
+import com.amazonaws.services.s3.model.lifecycle.LifecycleFilter;
 import de.latlon.xplan.commons.archive.ArchiveEntry;
 import de.latlon.xplan.commons.archive.XPlanArchiveContentAccess;
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Path;
-import java.util.List;
-
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
  * @since 7.0
@@ -58,13 +62,24 @@ public class S3Storage {
 		this.bucketName = bucketName;
 	}
 
+	public void setBucketExpirationDate(String id, int expirationInDays) throws StorageException {
+		createBucketIfNotExists();
+		BucketLifecycleConfiguration bucketLifecycleConfig = new BucketLifecycleConfiguration();
+		BucketLifecycleConfiguration.Rule rule = new BucketLifecycleConfiguration.Rule().withId(id)
+			.withExpirationInDays(expirationInDays)
+			.withStatus(ENABLED)
+			.withFilter(new LifecycleFilter());
+		bucketLifecycleConfig.withRules(rule);
+		client.setBucketLifecycleConfiguration(bucketName, bucketLifecycleConfig);
+	}
+
 	/**
 	 * @param key of the object to return
 	 * @return the S3Object with the passed key, never <code>null</code>
 	 * @throws StorageException if an error occurred requesting the object or an object
 	 * with the passed key was not found
 	 */
-	public de.latlon.xplan.manager.storage.s3.S3Object getObject(String key) throws StorageException {
+	public de.latlon.xplan.commons.s3.S3Object getObject(String key) throws StorageException {
 		S3Object object = null;
 		try {
 			LOG.info("Get object with key {} from bucket {}.", key, bucketName);
@@ -74,7 +89,7 @@ public class S3Storage {
 					objectMetadata.getContentLength());
 			ByteArrayOutputStream bos = new ByteArrayOutputStream();
 			object.getObjectContent().transferTo(bos);
-			return new de.latlon.xplan.manager.storage.s3.S3Object(s3Metadata, bos.toByteArray());
+			return new de.latlon.xplan.commons.s3.S3Object(s3Metadata, bos.toByteArray());
 		}
 		catch (AmazonServiceException | IOException e) {
 			throw new StorageException("Could not get object with key " + key + " from bucket " + bucketName + ".", e);
@@ -107,8 +122,9 @@ public class S3Storage {
 		return objectsToDelete.getObjectSummaries();
 	}
 
-	protected String insertObject(int planId, String entryName, XPlanArchiveContentAccess archive)
+	public String insertObject(int planId, String entryName, XPlanArchiveContentAccess archive)
 			throws StorageException {
+		createBucketIfNotExists();
 		String key = createKey(planId, entryName);
 		try {
 			LOG.info("Insert object with key {} in bucket {}.", key, bucketName);
@@ -127,17 +143,19 @@ public class S3Storage {
 		}
 	}
 
-	protected void insertObject(String key, Path file) throws StorageException {
+	public PutObjectResult insertObject(String key, Path file) throws StorageException {
+		createBucketIfNotExists();
 		try {
 			LOG.info("Insert object with key {} in bucket {}.", key, bucketName);
-			client.putObject(bucketName, key, file.toFile());
+			return client.putObject(bucketName, key, file.toFile());
 		}
 		catch (AmazonServiceException e) {
 			throw new StorageException("Could not insert object with key " + key + " in bucket " + bucketName + ".", e);
 		}
 	}
 
-	public void insertObject(de.latlon.xplan.manager.storage.s3.S3Object object) throws StorageException {
+	public void insertObject(de.latlon.xplan.commons.s3.S3Object object) throws StorageException {
+		createBucketIfNotExists();
 		String key = object.getS3Metadata().getKey();
 		try {
 			LOG.info("Insert object with key {} in bucket {}.", key, bucketName);
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/StorageException.java b/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/StorageException.java
similarity index 89%
rename from xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/StorageException.java
rename to xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/StorageException.java
index ff5dc2d202..198f42ef45 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/StorageException.java
+++ b/xplan-core/xplan-core-commons/src/main/java/de/latlon/xplan/commons/s3/StorageException.java
@@ -18,7 +18,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  * #L%
  */
-package de.latlon.xplan.manager.wmsconfig.raster.storage;
+package de.latlon.xplan.commons.s3;
 
 import com.amazonaws.AmazonServiceException;
 
@@ -35,6 +35,11 @@ public class StorageException extends Exception {
 			this.statusCode = ((AmazonServiceException) e).getStatusCode();
 	}
 
+	public StorageException(String message, int statusCode) {
+		super(message);
+		this.statusCode = statusCode;
+	}
+
 	public int getStatusCode() {
 		return statusCode;
 	}
diff --git a/xplan-core/xplan-core-manager/pom.xml b/xplan-core/xplan-core-manager/pom.xml
index 0805384960..2870fd8959 100644
--- a/xplan-core/xplan-core-manager/pom.xml
+++ b/xplan-core/xplan-core-manager/pom.xml
@@ -164,7 +164,6 @@
     <dependency>
       <groupId>io.findify</groupId>
       <artifactId>s3mock_2.13</artifactId>
-      <version>0.2.6</version>
       <scope>test</scope>
     </dependency>
     <dependency>
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/DocumentStorage.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/DocumentStorage.java
index 56806e16b0..906d814935 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/DocumentStorage.java
+++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/DocumentStorage.java
@@ -22,7 +22,7 @@ package de.latlon.xplan.manager.document;
 
 import de.latlon.xplan.commons.archive.XPlanArchive;
 import de.latlon.xplan.manager.storage.StorageEvent;
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
+import de.latlon.xplan.commons.s3.StorageException;
 
 import java.nio.file.Path;
 import java.util.List;
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/XPlanDocumentManager.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/XPlanDocumentManager.java
index 8fde067de2..1764ae100f 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/XPlanDocumentManager.java
+++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/XPlanDocumentManager.java
@@ -25,7 +25,7 @@ import de.latlon.xplan.commons.reference.ExternalReference;
 import de.latlon.xplan.commons.reference.ExternalReferenceInfo;
 import de.latlon.xplan.manager.edit.EditedArtefacts;
 import de.latlon.xplan.manager.storage.StorageEvent;
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
+import de.latlon.xplan.commons.s3.StorageException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.context.ApplicationEventPublisher;
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/s3/S3DocumentStorage.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/s3/S3DocumentStorage.java
index 17ea9de039..318db1a9ce 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/s3/S3DocumentStorage.java
+++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/s3/S3DocumentStorage.java
@@ -24,9 +24,9 @@ import com.amazonaws.services.s3.AmazonS3;
 import de.latlon.xplan.commons.archive.XPlanArchive;
 import de.latlon.xplan.manager.document.DocumentStorage;
 import de.latlon.xplan.manager.storage.StorageEvent;
-import de.latlon.xplan.manager.storage.s3.S3Object;
-import de.latlon.xplan.manager.storage.s3.S3Storage;
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
+import de.latlon.xplan.commons.s3.S3Object;
+import de.latlon.xplan.commons.s3.S3Storage;
+import de.latlon.xplan.commons.s3.StorageException;
 
 import java.nio.file.Path;
 import java.util.ArrayList;
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/s3/config/AmazonS3DocumentStorageContext.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/s3/config/AmazonS3DocumentStorageContext.java
index d6d362679c..313ac42727 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/s3/config/AmazonS3DocumentStorageContext.java
+++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/document/s3/config/AmazonS3DocumentStorageContext.java
@@ -42,7 +42,7 @@ public class AmazonS3DocumentStorageContext {
 
 	@Bean
 	public S3DocumentStorage documentStorage(AmazonS3 s3Client,
-			@Value("${s3.bucketName:#{environment.XPLAN_S3_BUCKET_NAME}}") String bucketName) {
+			@Value("${xplanbox.s3.bucketName:#{environment.XPLAN_S3_BUCKET_NAME}}") String bucketName) {
 		return new S3DocumentStorage(s3Client, bucketName);
 	}
 
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/StorageCleanUpManager.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/StorageCleanUpManager.java
index d342cd6f91..2b0278093e 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/StorageCleanUpManager.java
+++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/StorageCleanUpManager.java
@@ -20,7 +20,7 @@
  */
 package de.latlon.xplan.manager.storage;
 
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
+import de.latlon.xplan.commons.s3.StorageException;
 
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/StorageEvent.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/StorageEvent.java
index 688e8e0e5d..e81d45b641 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/StorageEvent.java
+++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/StorageEvent.java
@@ -20,7 +20,7 @@
  */
 package de.latlon.xplan.manager.storage;
 
-import de.latlon.xplan.manager.storage.s3.S3Object;
+import de.latlon.xplan.commons.s3.S3Object;
 
 import java.nio.file.Path;
 import java.util.ArrayList;
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/filesystem/FilesystemStorageCleanUpManager.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/filesystem/FilesystemStorageCleanUpManager.java
index cf12833a2d..2898356c89 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/filesystem/FilesystemStorageCleanUpManager.java
+++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/filesystem/FilesystemStorageCleanUpManager.java
@@ -23,7 +23,7 @@ package de.latlon.xplan.manager.storage.filesystem;
 import de.latlon.xplan.manager.storage.StorageCleanUpManager;
 import de.latlon.xplan.manager.storage.StorageEvent;
 import de.latlon.xplan.manager.wmsconfig.raster.storage.FileSystemStorage;
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
+import de.latlon.xplan.commons.s3.StorageException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/S3StorageCleanUpManager.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/S3StorageCleanUpManager.java
index bf213e712e..73673267d2 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/S3StorageCleanUpManager.java
+++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/S3StorageCleanUpManager.java
@@ -22,9 +22,11 @@ package de.latlon.xplan.manager.storage.s3;
 
 import com.amazonaws.services.s3.AmazonS3;
 import com.amazonaws.services.s3.model.S3ObjectSummary;
+import de.latlon.xplan.commons.s3.S3Object;
+import de.latlon.xplan.commons.s3.S3Storage;
 import de.latlon.xplan.manager.storage.StorageCleanUpManager;
 import de.latlon.xplan.manager.storage.StorageEvent;
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
+import de.latlon.xplan.commons.s3.StorageException;
 
 import java.util.List;
 
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3Context.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3Context.java
index b91778c0f3..8087bbe556 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3Context.java
+++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3Context.java
@@ -27,7 +27,7 @@ import com.amazonaws.client.builder.AwsClientBuilder;
 import com.amazonaws.services.s3.AmazonS3;
 import com.amazonaws.services.s3.AmazonS3ClientBuilder;
 import de.latlon.xplan.manager.storage.StorageCleanUpManager;
-import de.latlon.xplan.manager.storage.s3.S3Storage;
+import de.latlon.xplan.commons.s3.S3Storage;
 import de.latlon.xplan.manager.storage.s3.S3StorageCleanUpManager;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
@@ -49,8 +49,8 @@ public class AmazonS3Context {
 
 	@Bean(destroyMethod = "shutdown")
 	public AmazonS3 s3Client(AWSCredentials credentials,
-			@Value("${s3.region:#{environment.XPLAN_S3_REGION}}") String signingRegion,
-			@Value("${s3.endpoint.url:#{environment.XPLAN_S3_ENDPOINT}}") String endpointUrl) {
+			@Value("${xplanbox.s3.region:#{environment.XPLAN_S3_REGION}}") String signingRegion,
+			@Value("${xplanbox.s3.endpoint.url:#{environment.XPLAN_S3_ENDPOINT}}") String endpointUrl) {
 		AmazonS3 client;
 		// TODO refactoring if/else to @ConditionalOnExpression with SpringBoot into 2
 		// SpringBeans
@@ -72,20 +72,21 @@ public class AmazonS3Context {
 	}
 
 	@Bean
-	public AWSCredentials credentials(@Value("${s3.accessKeyId:#{environment.XPLAN_S3_ACCESS_KEY}}") String accessKeyId,
-			@Value("${s3.secretKey:#{environment.XPLAN_S3_SECRET_ACCESS_KEY}}") String secretKey) {
+	public AWSCredentials credentials(
+			@Value("${xplanbox.s3.accessKeyId:#{environment.XPLAN_S3_ACCESS_KEY}}") String accessKeyId,
+			@Value("${xplanbox.s3.secretKey:#{environment.XPLAN_S3_SECRET_ACCESS_KEY}}") String secretKey) {
 		return new BasicAWSCredentials(accessKeyId, secretKey);
 	}
 
 	@Bean
 	public StorageCleanUpManager storageCleanUpManager(AmazonS3 s3Client,
-			@Value("${s3.bucketName:#{environment.XPLAN_S3_BUCKET_NAME}}") String bucketName) {
+			@Value("${xplanbox.s3.bucketName:#{environment.XPLAN_S3_BUCKET_NAME}}") String bucketName) {
 		return new S3StorageCleanUpManager(s3Client, bucketName);
 	}
 
 	@Bean
 	public S3Storage rollbackStorage(AmazonS3 s3Client,
-			@Value("${s3.bucketName:#{environment.XPLAN_S3_BUCKET_NAME}}") String bucketName) {
+			@Value("${xplanbox.s3.bucketName:#{environment.XPLAN_S3_BUCKET_NAME}}") String bucketName) {
 		return new S3Storage(s3Client, bucketName);
 	}
 
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/listener/S3TransactionListener.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/listener/S3TransactionListener.java
index d4fc106de3..c5b02d943d 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/listener/S3TransactionListener.java
+++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/storage/s3/listener/S3TransactionListener.java
@@ -21,9 +21,9 @@
 package de.latlon.xplan.manager.storage.s3.listener;
 
 import de.latlon.xplan.manager.storage.StorageEvent;
-import de.latlon.xplan.manager.storage.s3.S3Object;
-import de.latlon.xplan.manager.storage.s3.S3Storage;
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
+import de.latlon.xplan.commons.s3.S3Object;
+import de.latlon.xplan.commons.s3.S3Storage;
+import de.latlon.xplan.commons.s3.StorageException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Qualifier;
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/transaction/service/XPlanDeleteService.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/transaction/service/XPlanDeleteService.java
index 06b8f29388..93282c6cd8 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/transaction/service/XPlanDeleteService.java
+++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/transaction/service/XPlanDeleteService.java
@@ -23,7 +23,7 @@ package de.latlon.xplan.manager.transaction.service;
 import de.latlon.xplan.manager.database.XPlanManagerDao;
 import de.latlon.xplan.manager.storage.StorageCleanUpManager;
 import de.latlon.xplan.manager.storage.StorageEvent;
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
+import de.latlon.xplan.commons.s3.StorageException;
 import org.springframework.context.ApplicationEventPublisher;
 
 import jakarta.transaction.Transactional;
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/transaction/service/XPlanEditService.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/transaction/service/XPlanEditService.java
index 76a21df86e..1b86828c46 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/transaction/service/XPlanEditService.java
+++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/transaction/service/XPlanEditService.java
@@ -26,7 +26,7 @@ import de.latlon.xplan.manager.document.XPlanDocumentManager;
 import de.latlon.xplan.manager.edit.EditedArtefacts;
 import de.latlon.xplan.manager.web.shared.PlanStatus;
 import de.latlon.xplan.manager.web.shared.XPlan;
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
+import de.latlon.xplan.commons.s3.StorageException;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import org.deegree.feature.FeatureCollection;
 
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/transaction/service/XPlanInsertService.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/transaction/service/XPlanInsertService.java
index e2c8846c35..41cc2a7f5c 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/transaction/service/XPlanInsertService.java
+++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/transaction/service/XPlanInsertService.java
@@ -29,7 +29,7 @@ import de.latlon.xplan.manager.database.XPlanManagerDao;
 import de.latlon.xplan.manager.document.XPlanDocumentManager;
 import de.latlon.xplan.manager.transaction.PlanImportData;
 import de.latlon.xplan.manager.web.shared.PlanStatus;
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
+import de.latlon.xplan.commons.s3.StorageException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/XPlanRasterManager.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/XPlanRasterManager.java
index 9b50e576fc..2683ed0906 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/XPlanRasterManager.java
+++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/XPlanRasterManager.java
@@ -28,7 +28,7 @@ import de.latlon.xplan.manager.storage.StorageEvent;
 import de.latlon.xplan.manager.web.shared.PlanStatus;
 import de.latlon.xplan.manager.wmsconfig.raster.config.RasterConfigManager;
 import de.latlon.xplan.manager.wmsconfig.raster.storage.RasterStorage;
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
+import de.latlon.xplan.commons.s3.StorageException;
 import de.latlon.xplan.manager.workspace.WorkspaceException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/RasterStorage.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/RasterStorage.java
index 73d108de24..420216fc45 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/RasterStorage.java
+++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/RasterStorage.java
@@ -21,6 +21,7 @@
 package de.latlon.xplan.manager.wmsconfig.raster.storage;
 
 import de.latlon.xplan.commons.archive.XPlanArchiveContentAccess;
+import de.latlon.xplan.commons.s3.StorageException;
 import de.latlon.xplan.manager.storage.StorageEvent;
 
 import java.io.IOException;
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorage.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorage.java
index 1a2e939b7a..2414e71ccf 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorage.java
+++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorage.java
@@ -23,10 +23,10 @@ package de.latlon.xplan.manager.wmsconfig.raster.storage.s3;
 import com.amazonaws.services.s3.AmazonS3;
 import de.latlon.xplan.commons.archive.XPlanArchiveContentAccess;
 import de.latlon.xplan.manager.storage.StorageEvent;
-import de.latlon.xplan.manager.storage.s3.S3Object;
-import de.latlon.xplan.manager.storage.s3.S3Storage;
+import de.latlon.xplan.commons.s3.S3Object;
+import de.latlon.xplan.commons.s3.S3Storage;
 import de.latlon.xplan.manager.wmsconfig.raster.storage.RasterStorage;
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
+import de.latlon.xplan.commons.s3.StorageException;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 
 /**
@@ -45,7 +45,6 @@ public class S3RasterStorage extends S3Storage implements RasterStorage {
 	@SuppressFBWarnings(value = "PATH_TRAVERSAL_IN")
 	public String addRasterFile(int planId, String referenceEntryName, String georefEntryName,
 			XPlanArchiveContentAccess archive, StorageEvent storageEvent) throws StorageException {
-		createBucketIfNotExists();
 		String objectKey = insertObject(planId, referenceEntryName, archive);
 		storageEvent.addInsertedKey(objectKey);
 		if (georefEntryName != null) {
diff --git a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/config/AmazonS3RasterStorageContext.java b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/config/AmazonS3RasterStorageContext.java
index a10f3c7403..0305d17b65 100644
--- a/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/config/AmazonS3RasterStorageContext.java
+++ b/xplan-core/xplan-core-manager/src/main/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/config/AmazonS3RasterStorageContext.java
@@ -47,7 +47,7 @@ public class AmazonS3RasterStorageContext {
 
 	@Bean
 	public S3RasterStorage rasterStorage(AmazonS3 s3Client,
-			@Value("${s3.bucketName:#{environment.XPLAN_S3_BUCKET_NAME}}") String bucketName) {
+			@Value("${xplanbox.s3.bucketName:#{environment.XPLAN_S3_BUCKET_NAME}}") String bucketName) {
 		return new S3RasterStorage(s3Client, bucketName);
 	}
 
diff --git a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/document/s3/S3DocumentStorageIT.java b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/document/s3/S3DocumentStorageIT.java
index b697547fa8..498a1d7f98 100644
--- a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/document/s3/S3DocumentStorageIT.java
+++ b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/document/s3/S3DocumentStorageIT.java
@@ -25,7 +25,7 @@ import de.latlon.xplan.commons.archive.XPlanArchiveCreator;
 import de.latlon.xplan.manager.document.s3.config.AmazonS3DocumentStorageContext;
 import de.latlon.xplan.manager.storage.StorageEvent;
 import de.latlon.xplan.manager.storage.s3.config.AmazonS3TestContext;
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
+import de.latlon.xplan.commons.s3.StorageException;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
diff --git a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/S3StorageCleanUpManagerTest.java b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/S3StorageCleanUpManagerTest.java
index 95714db597..07ced67fa9 100644
--- a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/S3StorageCleanUpManagerTest.java
+++ b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/S3StorageCleanUpManagerTest.java
@@ -27,7 +27,7 @@ import com.amazonaws.services.s3.model.S3Object;
 import com.amazonaws.services.s3.model.S3ObjectInputStream;
 import com.amazonaws.services.s3.model.S3ObjectSummary;
 import de.latlon.xplan.manager.storage.StorageEvent;
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
+import de.latlon.xplan.commons.s3.StorageException;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 
@@ -74,8 +74,8 @@ public class S3StorageCleanUpManagerTest {
 
 		verify(client).listObjects(BUCKET_NAME, "1_");
 		verify(client).deleteObject(BUCKET_NAME, "1_test.png");
-		ArgumentCaptor<de.latlon.xplan.manager.storage.s3.S3Object> argument = ArgumentCaptor
-			.forClass(de.latlon.xplan.manager.storage.s3.S3Object.class);
+		ArgumentCaptor<de.latlon.xplan.commons.s3.S3Object> argument = ArgumentCaptor
+			.forClass(de.latlon.xplan.commons.s3.S3Object.class);
 		verify(storageEvent).addDeletedKey(argument.capture());
 		assertThat(argument.getValue().getS3Metadata().getKey(), is("1_test.png"));
 	}
diff --git a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/S3StorageTestManual.java b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/S3StorageTestManual.java
index 8f9cdd8636..453f98b547 100644
--- a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/S3StorageTestManual.java
+++ b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/S3StorageTestManual.java
@@ -22,9 +22,12 @@ package de.latlon.xplan.manager.storage.s3;
 
 import de.latlon.xplan.commons.archive.XPlanArchiveContentAccess;
 import de.latlon.xplan.commons.archive.XPlanArchiveCreator;
+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.manager.storage.s3.config.AmazonS3TestContext;
 import de.latlon.xplan.manager.storage.s3.config.S3StorageTestContext;
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
+import de.latlon.xplan.commons.s3.StorageException;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
diff --git a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3TestContext.java b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3TestContext.java
index c69428f645..e989e049de 100644
--- a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3TestContext.java
+++ b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/config/AmazonS3TestContext.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%
@@ -66,8 +66,10 @@ public class AmazonS3TestContext {
 	@Bean
 	@Primary
 	@Profile("mock")
-	public AmazonS3 s3TestClient(@Value("${s3.region}") String signingRegion,
-			@Value("${s3.bucketName}") String bucketName, @Value("${s3.endpoint.url}") String url) {
+	public AmazonS3 s3TestClient(@Value("${xplanbox.s3.region}") String signingRegion,
+			@Value("${xplanbox.s3.bucketName}") String bucketName, @Value("${xplanbox.s3.endpoint.url}") String url) {
+
+		System.out.println("region: " + signingRegion + ", bucket: " + bucketName + ", url: " + url);
 		AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration(url + ":" + port,
 				signingRegion);
 		AmazonS3 client = AmazonS3ClientBuilder.standard()
@@ -84,7 +86,6 @@ public class AmazonS3TestContext {
 		s3TestClient.shutdown();
 		if (s3Mock != null) {
 			s3Mock.stop();
-			s3Mock.shutdown();
 		}
 	}
 
diff --git a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/config/S3StorageTestContext.java b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/config/S3StorageTestContext.java
index 1a8b23ca61..f65645921d 100644
--- a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/config/S3StorageTestContext.java
+++ b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/storage/s3/config/S3StorageTestContext.java
@@ -21,7 +21,7 @@
 package de.latlon.xplan.manager.storage.s3.config;
 
 import com.amazonaws.services.s3.AmazonS3;
-import de.latlon.xplan.manager.storage.s3.S3Storage;
+import de.latlon.xplan.commons.s3.S3Storage;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -34,7 +34,7 @@ public class S3StorageTestContext {
 
 	@Bean
 	public S3Storage rollbackStorage(AmazonS3 s3Client,
-			@Value("${s3.bucketName:#{environment.XPLAN_S3_BUCKET_NAME}}") String bucketName) {
+			@Value("${xplanbox.s3.bucketName:#{environment.XPLAN_S3_BUCKET_NAME}}") String bucketName) {
 		return new S3Storage(s3Client, bucketName);
 	}
 
diff --git a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorageTest.java b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorageTest.java
index 5bc5da6cc0..1f8e76df11 100644
--- a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorageTest.java
+++ b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorageTest.java
@@ -20,36 +20,25 @@
  */
 package de.latlon.xplan.manager.wmsconfig.raster.storage.s3;
 
+import static org.hamcrest.CoreMatchers.hasItems;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.List;
+
 import com.amazonaws.services.s3.AmazonS3;
-import com.amazonaws.services.s3.model.ObjectListing;
-import com.amazonaws.services.s3.model.ObjectMetadata;
-import com.amazonaws.services.s3.model.S3Object;
-import com.amazonaws.services.s3.model.S3ObjectInputStream;
-import com.amazonaws.services.s3.model.S3ObjectSummary;
+import com.amazonaws.services.s3.model.*;
 import de.latlon.xplan.commons.archive.ArchiveEntry;
 import de.latlon.xplan.commons.archive.XPlanArchiveContentAccess;
+import de.latlon.xplan.commons.s3.StorageException;
 import de.latlon.xplan.manager.storage.StorageEvent;
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Collections;
-import java.util.List;
-
-import static org.hamcrest.CoreMatchers.hasItems;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
  */
@@ -58,7 +47,7 @@ public class S3RasterStorageTest {
 	private static final String BUCKET_NAME = "xplanbox";
 
 	@Test
-	public void testAddRasterFile() throws IOException, StorageException {
+	public void testAddRasterFile() throws StorageException {
 		AmazonS3 client = spy(AmazonS3.class);
 		S3RasterStorage s3RasterStorage = new S3RasterStorage(client, BUCKET_NAME);
 		XPlanArchiveContentAccess archive = mockArchive();
@@ -67,7 +56,7 @@ public class S3RasterStorageTest {
 		String key = s3RasterStorage.addRasterFile(1, "test.png", "test.png.aux.xml", archive, storageEvent);
 		ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
 		assertThat(key, is("1_test.png"));
-		verify(client).doesBucketExistV2(eq(BUCKET_NAME));
+		verify(client, times(2)).doesBucketExistV2(eq(BUCKET_NAME));
 		verify(client, times(2)).putObject(eq(BUCKET_NAME), captor.capture(), nullable(InputStream.class),
 				any(ObjectMetadata.class));
 		assertThat(captor.getAllValues(), hasItems("1_test.png", "1_test.png.aux.xml"));
@@ -99,8 +88,8 @@ public class S3RasterStorageTest {
 		s3RasterStorage.deleteRasterFile(1, "test.png", storageEvent);
 
 		verify(client).deleteObject(BUCKET_NAME, "1_test.png");
-		ArgumentCaptor<de.latlon.xplan.manager.storage.s3.S3Object> argument = ArgumentCaptor
-			.forClass(de.latlon.xplan.manager.storage.s3.S3Object.class);
+		ArgumentCaptor<de.latlon.xplan.commons.s3.S3Object> argument = ArgumentCaptor
+			.forClass(de.latlon.xplan.commons.s3.S3Object.class);
 		verify(storageEvent).addDeletedKey(argument.capture());
 		assertThat(argument.getValue().getS3Metadata().getKey(), is("1_test.png"));
 	}
diff --git a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorageTestManual.java b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorageTestManual.java
index 90706d7dc0..fb0fb651cb 100644
--- a/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorageTestManual.java
+++ b/xplan-core/xplan-core-manager/src/test/java/de/latlon/xplan/manager/wmsconfig/raster/storage/s3/S3RasterStorageTestManual.java
@@ -23,9 +23,9 @@ package de.latlon.xplan.manager.wmsconfig.raster.storage.s3;
 import de.latlon.xplan.commons.archive.XPlanArchiveContentAccess;
 import de.latlon.xplan.commons.archive.XPlanArchiveCreator;
 import de.latlon.xplan.manager.storage.StorageEvent;
-import de.latlon.xplan.manager.storage.s3.S3Object;
+import de.latlon.xplan.commons.s3.S3Object;
 import de.latlon.xplan.manager.storage.s3.config.AmazonS3TestContext;
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
+import de.latlon.xplan.commons.s3.StorageException;
 import de.latlon.xplan.manager.wmsconfig.raster.storage.s3.config.AmazonS3RasterStorageContext;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/xplan-core/xplan-core-manager/src/test/resources/s3Mock.properties b/xplan-core/xplan-core-manager/src/test/resources/s3Mock.properties
index 3edcb5508b..419aaa99b2 100644
--- a/xplan-core/xplan-core-manager/src/test/resources/s3Mock.properties
+++ b/xplan-core/xplan-core-manager/src/test/resources/s3Mock.properties
@@ -18,8 +18,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 # #L%
 ###
-s3.accessKeyId=
-s3.secretKey=
-s3.bucketName=latlonxpb
-s3.region=eu-central-1
-s3.endpoint.url=http://localhost
+xplanbox.s3.accessKeyId=
+xplanbox.s3.secretKey=
+xplanbox.s3.bucketName=latlonxpb
+xplanbox.s3.region=eu-central-1
+xplanbox.s3.endpoint.url=http://localhost
diff --git a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationRequestNotifier.java b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/EventSender.java
similarity index 87%
rename from xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationRequestNotifier.java
rename to xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/EventSender.java
index e88f76163b..5feb9fe096 100644
--- a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationRequestNotifier.java
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/EventSender.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%
@@ -22,10 +22,12 @@ package de.latlon.core.validator.events;
 
 /**
  * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
- * @since 7.2
+ * @since 8.0
  */
-public interface ValidationRequestNotifier {
+public interface EventSender {
 
-	void sendEvent(ValidationRequestedEvent event);
+	void sendEvent(XPlanboxInternalEvent e);
+
+	void sendPublicEvent(XPlanboxPublicEvent e);
 
 }
diff --git a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitConfig.java b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitConfig.java
index 1c15bcc22f..a89b1713b6 100644
--- a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitConfig.java
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitConfig.java
@@ -8,25 +8,30 @@
  * 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.core.validator.events;
 
-import org.springframework.amqp.core.Binding;
-import org.springframework.amqp.core.BindingBuilder;
-import org.springframework.amqp.core.Queue;
-import org.springframework.amqp.core.TopicExchange;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.amqp.core.FanoutExchange;
 import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
 import org.springframework.context.annotation.Profile;
 
 /**
@@ -34,33 +39,47 @@ import org.springframework.context.annotation.Profile;
  * @since 7.2
  */
 @Configuration
-@Profile("rabbit")
+@Import({ ValidationTaskQueueConfig.class })
+@Profile("!test")
 public class RabbitConfig {
 
-	@Bean
-	RabbitSettings rabbitSettings() {
-		return new RabbitSettings();
-	}
+	@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+	@Retention(RetentionPolicy.RUNTIME)
+	@Qualifier
+	@interface InternalFanout {
 
-	@Bean
-	Queue queue(RabbitSettings rabbitSettings) {
-		return new Queue(rabbitSettings.getInternalQueueName(), true);
 	}
 
-	@Bean
-	TopicExchange exchange(RabbitSettings rabbitSettings) {
-		return new TopicExchange(rabbitSettings.getInternalExchangeName());
+	@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+	@Retention(RetentionPolicy.RUNTIME)
+	@Qualifier
+	@interface PublicFanout {
+
 	}
 
 	@Bean
-	Binding binding(Queue queue, TopicExchange exchange) {
-		return BindingBuilder.bind(queue).to(exchange).with("foo.bar.#");
+	@ConditionalOnMissingBean(RabbitSettings.class)
+	RabbitSettings rabbitSettings() {
+		return new RabbitSettings();
 	}
 
 	@Bean
+	@ConditionalOnMissingBean(Jackson2JsonMessageConverter.class)
 	public Jackson2JsonMessageConverter jsonMessageConverter() {
 		Jackson2JsonMessageConverter jsonConverter = new Jackson2JsonMessageConverter();
 		return jsonConverter;
 	}
 
+	@Bean
+	@InternalFanout
+	public FanoutExchange internalFanoutExchange(RabbitSettings rabbitSettings) {
+		return new FanoutExchange(rabbitSettings.getInternalFanoutName());
+	}
+
+	@Bean
+	@PublicFanout
+	public FanoutExchange publicFanoutExchange(RabbitSettings rabbitSettings) {
+		return new FanoutExchange(rabbitSettings.getPublicFanoutName());
+	}
+
 }
diff --git a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitEmitterConfig.java b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitEmitterConfig.java
index b6440f7f6b..d511e5bc04 100644
--- a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitEmitterConfig.java
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitEmitterConfig.java
@@ -8,57 +8,42 @@
  * 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.core.validator.events;
 
-import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.core.FanoutExchange;
 import org.springframework.amqp.rabbit.core.RabbitTemplate;
-import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 import org.springframework.context.annotation.Profile;
 
-@Configuration
-@Import({ RabbitConfig.class })
+import de.latlon.core.validator.events.RabbitConfig.InternalFanout;
+import de.latlon.core.validator.events.RabbitConfig.PublicFanout;
+
 /**
  * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
  * @since 7.2
  */
+@Configuration
+@Import({ RabbitConfig.class })
+@Profile("!test")
 public class RabbitEmitterConfig {
 
 	@Bean
-	@Profile("rabbit")
-	public RabbitTemplate rabbitTemplate(Jackson2JsonMessageConverter msgConverter, ConnectionFactory connectionFactory,
+	EventSender validationRequestNotifier(RabbitTemplate rabbitTemplate,
+			@InternalFanout FanoutExchange internalFanoutExchange, @PublicFanout FanoutExchange publicFanoutExchange,
 			RabbitSettings rabbitSettings) {
-		RabbitTemplate template = new RabbitTemplate();
-		template.setMessageConverter(msgConverter);
-		template.setConnectionFactory(connectionFactory);
-		template.setExchange(rabbitSettings.getInternalExchangeName());
-
-		return template;
-	}
-
-	@Bean
-	@Profile("rabbit")
-	ValidationRequestNotifier validationRequestNotifier(RabbitTemplate rabbitTemplate) {
-		return new RabbitValidationRequestNotifier(rabbitTemplate);
-	}
-
-	@Bean
-	@Profile("!rabbit")
-	ValidationRequestNotifier noOpValidationRequestNotifier(RabbitTemplate rabbitTemplate) {
-		return (ValidationRequestedEvent event) -> {
-		};
+		return new RabbitEventSender(rabbitTemplate, internalFanoutExchange, publicFanoutExchange, rabbitSettings);
 	}
 
 }
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
new file mode 100644
index 0000000000..82ca44ac29
--- /dev/null
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitEventSender.java
@@ -0,0 +1,81 @@
+/*-
+ * #%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.core.validator.events;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.springframework.amqp.core.FanoutExchange;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+
+/**
+ * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
+ * @since 7.2
+ */
+class RabbitEventSender implements EventSender {
+
+	private static final Logger LOG = getLogger(RabbitEventSender.class);
+
+	private final RabbitTemplate rabbitTemplate;
+
+	private final String publicFanoutExchangeName;
+
+	private final String internalFanoutExchangeName;
+
+	private final Map<Class<?>, String> taskClass2QueueName = new HashMap<>();
+
+	public RabbitEventSender(RabbitTemplate rabbitTemplate, FanoutExchange internalFanoutExchange,
+			FanoutExchange publicFanoutExchange, RabbitSettings rabbitSettings) {
+		this.internalFanoutExchangeName = internalFanoutExchange.getName();
+		this.publicFanoutExchangeName = publicFanoutExchange.getName();
+		this.rabbitTemplate = rabbitTemplate;
+
+		taskClass2QueueName.put(ValidationRequestedEvent.class, rabbitSettings.getInternalValidationWorkQueueName());
+	}
+
+	public void sendEvent(XPlanboxInternalEvent event) {
+		if (event instanceof XPlanboxInternalTaskEvent) {
+			String workQueueName = taskClass2QueueName.get(event.getClass());
+			if (workQueueName == null) {
+				LOG.error("Ignoring task: no queue configured to send event to (" + event + ")");
+			}
+			else {
+				LOG.info("Sending task event: " + event);
+				rabbitTemplate.convertAndSend(workQueueName, event);
+			}
+		}
+		else {
+			LOG.info("Sending fanout event: " + event);
+			rabbitTemplate.convertAndSend(internalFanoutExchangeName, "fanout." + event.getClass().getSimpleName(),
+					event);
+		}
+	}
+
+	@Override
+	public void sendPublicEvent(XPlanboxPublicEvent 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/RabbitReceiverConfig.java b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitReceiverConfig.java
index 3ca256f480..0fb4ed1f40 100644
--- a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitReceiverConfig.java
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitReceiverConfig.java
@@ -8,58 +8,49 @@
  * 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.core.validator.events;
 
-import org.springframework.amqp.rabbit.connection.ConnectionFactory;
-import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
-import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
-import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
+import org.springframework.amqp.core.AnonymousQueue;
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.BindingBuilder;
+import org.springframework.amqp.core.FanoutExchange;
+import org.springframework.amqp.core.Queue;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 import org.springframework.context.annotation.Profile;
 
+import de.latlon.core.validator.events.RabbitConfig.InternalFanout;
+
 /**
  * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
  * @since 7.2
  */
 @Configuration
 @Import({ RabbitConfig.class })
+@Profile("!test")
 public class RabbitReceiverConfig {
 
 	@Bean
-	@Profile("rabbit")
-	SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
-			MessageListenerAdapter listenerAdapter, RabbitSettings rabbitSettings) {
-		SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
-		container.setConnectionFactory(connectionFactory);
-		container.setQueueNames(rabbitSettings.getInternalQueueName());
-		container.setMessageListener(listenerAdapter);
-		return container;
-	}
-
-	@Bean
-	@Profile("rabbit")
-	MessageListenerAdapter listenerAdapter(ValidationMessageReceiver receiver,
-			Jackson2JsonMessageConverter msgConverter) {
-		MessageListenerAdapter listenerAdapter = new MessageListenerAdapter(receiver, "receiveMessage");
-		listenerAdapter.setMessageConverter(msgConverter);
-		return listenerAdapter;
+	@InternalFanout
+	public Queue internalFanoutQueue() {
+		return new AnonymousQueue();
 	}
 
 	@Bean
-	ValidationMessageReceiver validationMessageReceiver() {
-		return new ValidationMessageReceiver();
+	@InternalFanout
+	public Binding internalFanoutBinding(@InternalFanout FanoutExchange fanout, @InternalFanout Queue fanoutQueue) {
+		return BindingBuilder.bind(fanoutQueue).to(fanout);
 	}
 
 }
diff --git a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitSettings.java b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitSettings.java
index cc9e958218..06f34440aa 100644
--- a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitSettings.java
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitSettings.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%
@@ -28,19 +28,37 @@ import org.springframework.beans.factory.annotation.Value;
  */
 class RabbitSettings {
 
-	private static final String topicExchangeName = "-internal-exchange";
+	private static final String suffixInternalFanoutName = "-internal-fanout";
 
-	private static final String queueName = "-internal-queue";
+	private static final String suffixPublicFanoutName = "-public-fanout";
+
+	private static final String suffixTopicExchangeName = "-internal-exchange";
+
+	private static final String suffixValidationWorkQueueName = "-internal-validation-queue";
 
 	@Value("${xplanbox.rabbitmq.internal.prefix}")
 	private String internalPrefix;
 
-	public String getInternalQueueName() {
-		return internalPrefix + queueName;
+	@Value("${xplanbox.rabbitmq.public.fanout}")
+	private String publicFanoutName;
+
+	public String getInternalValidationWorkQueueName() {
+		return internalPrefix + suffixValidationWorkQueueName;
 	}
 
 	public String getInternalExchangeName() {
-		return internalPrefix + topicExchangeName;
+		return internalPrefix + suffixTopicExchangeName;
+	}
+
+	public String getInternalFanoutName() {
+		return internalPrefix + suffixInternalFanoutName;
+	}
+
+	public String getPublicFanoutName() {
+		if (publicFanoutName != null && !publicFanoutName.isBlank()) {
+			return publicFanoutName;
+		}
+		return internalPrefix + suffixPublicFanoutName;
 	}
 
 }
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
new file mode 100644
index 0000000000..b4cb999c16
--- /dev/null
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationFinishedEvent.java
@@ -0,0 +1,62 @@
+/*-
+ * #%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.core.validator.events;
+
+/**
+ * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
+ * @since 8.0
+ */
+public class ValidationFinishedEvent extends XPlanboxInternalFanoutEvent {
+
+	private String uuid;
+
+	private ValidationFinishedStatus validationFinishedStatus;
+
+	public enum ValidationFinishedStatus {
+
+		SUCCEEDED, FAILED
+
+	}
+
+	public ValidationFinishedEvent() {
+
+	}
+
+	public ValidationFinishedEvent(String uuid, ValidationFinishedStatus validationFinishedStatus) {
+		this.uuid = uuid;
+		this.validationFinishedStatus = validationFinishedStatus;
+	}
+
+	@Override
+	public String toString() {
+		return getClass().getSimpleName() + "(" + uuid + ", validationFinishedStatus: " + validationFinishedStatus
+				+ ")";
+	}
+
+	public String getUuid() {
+		return uuid;
+	}
+
+	public ValidationFinishedStatus getValidationFinishedStatus() {
+		return validationFinishedStatus;
+	}
+
+}
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 2caec823e6..0a5a90c09d 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
@@ -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%
@@ -26,25 +26,89 @@ 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 {
+public class ValidationRequestedEvent extends XPlanboxInternalTaskEvent {
+
+	public enum MediaType {
+
+		ZIP("application/zip", ".zip"), PDF("application/pdf", ".pdf"), JSON("application/json", ".json"),
+		XML("application/xml", ".xml");
+
+		private final String mimeType;
+
+		private final String fileExtension;
+
+		MediaType(String mimeType, String fileExtension) {
+			this.mimeType = mimeType;
+			this.fileExtension = fileExtension;
+		}
+
+		public String getFileExtension() {
+			return fileExtension;
+		}
+
+		public String getMimeType() {
+			return mimeType;
+		}
+
+	}
+
+	public enum OriginFile {
+
+		ZIP, GML
+
+	}
 
 	private ValidationSettings settings;
 
+	private String uuid;
+
+	private MediaType requestedMediaType;
+
+	private String xFileName;
+
+	private OriginFile originFile;
+
 	public ValidationRequestedEvent() {
 
 	}
 
-	public ValidationRequestedEvent(ValidationSettings settings) {
+	public ValidationRequestedEvent(ValidationSettings settings, String xFileName, MediaType requestedMediaType,
+			OriginFile originFile) {
+		this(null, settings, xFileName, requestedMediaType, originFile);
+	}
+
+	public ValidationRequestedEvent(String uuid, ValidationSettings settings, String xFileName,
+			MediaType requestedMediaType, OriginFile originFile) {
+		this.uuid = uuid;
 		this.settings = settings;
+		this.xFileName = xFileName;
+		this.requestedMediaType = requestedMediaType;
+		this.originFile = originFile;
+	}
+
+	public OriginFile getOriginFile() {
+		return originFile;
+	}
+
+	public MediaType getRequestedMediaType() {
+		return requestedMediaType;
 	}
 
 	public ValidationSettings getSettings() {
 		return settings;
 	}
 
+	public String getUuid() {
+		return uuid;
+	}
+
+	public String getxFileName() {
+		return xFileName;
+	}
+
 	@Override
 	public String toString() {
-		return settings.toString();
+		return "settings: " + settings + ", uuid: " + uuid;
 	}
 
 }
diff --git a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationTaskQueueConfig.java b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationTaskQueueConfig.java
new file mode 100644
index 0000000000..4546be5313
--- /dev/null
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationTaskQueueConfig.java
@@ -0,0 +1,13 @@
+package de.latlon.core.validator.events;
+
+import org.springframework.amqp.core.Queue;
+import org.springframework.context.annotation.Bean;
+
+public class ValidationTaskQueueConfig {
+
+	@Bean
+	public Queue validationTaskQueue(RabbitSettings rabbitSettings) {
+		return new Queue(rabbitSettings.getInternalValidationWorkQueueName(), true);
+	}
+
+}
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/XPlanboxInternalEvent.java
new file mode 100644
index 0000000000..b162e1b17e
--- /dev/null
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxInternalEvent.java
@@ -0,0 +1,11 @@
+package de.latlon.core.validator.events;
+
+/**
+ * Marker interface for internal events.
+ * 
+ * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
+ * @since 8.0
+ */
+public sealed interface XPlanboxInternalEvent permits XPlanboxInternalFanoutEvent, XPlanboxInternalTaskEvent {
+
+}
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/XPlanboxInternalFanoutEvent.java
new file mode 100644
index 0000000000..a05b1dc6a3
--- /dev/null
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxInternalFanoutEvent.java
@@ -0,0 +1,11 @@
+package de.latlon.core.validator.events;
+
+/**
+ * Base class for internal fanout events.
+ * 
+ * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
+ * @since 8.0
+ */
+public non-sealed class XPlanboxInternalFanoutEvent implements XPlanboxInternalEvent {
+
+}
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/XPlanboxInternalTaskEvent.java
new file mode 100644
index 0000000000..001926cde6
--- /dev/null
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxInternalTaskEvent.java
@@ -0,0 +1,11 @@
+package de.latlon.core.validator.events;
+
+/**
+ * Base class for internal task events.
+ * 
+ * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
+ * @since 8.0
+ */
+public non-sealed class XPlanboxInternalTaskEvent implements XPlanboxInternalEvent {
+
+}
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/XPlanboxPublicEvent.java
new file mode 100644
index 0000000000..bed8dedce3
--- /dev/null
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/XPlanboxPublicEvent.java
@@ -0,0 +1,11 @@
+package de.latlon.core.validator.events;
+
+/**
+ * Marker interface for public events.
+ * 
+ * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
+ * @since 8.0
+ */
+public interface XPlanboxPublicEvent {
+
+}
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/XPlanboxPublicV1Event.java
new file mode 100644
index 0000000000..04584a233d
--- /dev/null
+++ b/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/v1/XPlanboxPublicV1Event.java
@@ -0,0 +1,78 @@
+package de.latlon.core.validator.events.v1;
+
+import java.util.Objects;
+
+import de.latlon.core.validator.events.XPlanboxPublicEvent;
+
+/**
+ * V1 public event.
+ *
+ * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
+ * @since 8.0
+ */
+public class XPlanboxPublicV1Event implements XPlanboxPublicEvent {
+
+	public static enum EventType {
+
+		VALIDATION_START, VALIDATION_FINISHED
+
+	}
+
+	private String apiVersion = "1.0";
+
+	private EventType eventType;
+
+	private String uuid;
+
+	private String message;
+
+	public XPlanboxPublicV1Event() {
+
+	}
+
+	public XPlanboxPublicV1Event(EventType eventType, String uuid, String message) {
+		this.eventType = eventType;
+		this.uuid = uuid;
+		this.message = message;
+	}
+
+	public String getApiVersion() {
+		return apiVersion;
+	}
+
+	public EventType getEventType() {
+		return eventType;
+	}
+
+	public String getMessage() {
+		return message;
+	}
+
+	public String getUuid() {
+		return uuid;
+	}
+
+	@Override
+	public int hashCode() {
+		return Objects.hash(apiVersion, eventType, message, uuid);
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		XPlanboxPublicV1Event other = (XPlanboxPublicV1Event) obj;
+		return Objects.equals(apiVersion, other.apiVersion) && eventType == other.eventType
+				&& Objects.equals(message, other.message) && Objects.equals(uuid, other.uuid);
+	}
+
+	@Override
+	public String toString() {
+		return "XPlanboxPublicV1Event(" + eventType + ", " + uuid + ", " + message + ")";
+	}
+
+}
diff --git a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitValidationRequestNotifier.java b/xplan-core/xplan-core-validator-events/src/test/java/de/latlon/core/validator/events/ValidationFinishedEventTest.java
similarity index 57%
rename from xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitValidationRequestNotifier.java
rename to xplan-core/xplan-core-validator-events/src/test/java/de/latlon/core/validator/events/ValidationFinishedEventTest.java
index 192a545be9..aa0e0a6818 100644
--- a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/RabbitValidationRequestNotifier.java
+++ b/xplan-core/xplan-core-validator-events/src/test/java/de/latlon/core/validator/events/ValidationFinishedEventTest.java
@@ -20,28 +20,25 @@
  */
 package de.latlon.core.validator.events;
 
-import static org.slf4j.LoggerFactory.getLogger;
+import static de.latlon.core.validator.events.ValidationFinishedEvent.ValidationFinishedStatus.SUCCEEDED;
+import static org.assertj.core.api.Assertions.assertThat;
 
-import org.slf4j.Logger;
-import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.Test;
 
-/**
- * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
- * @since 7.2
- */
-class RabbitValidationRequestNotifier implements ValidationRequestNotifier {
+class ValidationFinishedEventTest {
 
-	private static final Logger LOG = getLogger(RabbitValidationRequestNotifier.class);
+	@Test
+	void jsonSerializeAndDeserialize() throws Exception {
+		ValidationFinishedEvent event = new ValidationFinishedEvent("my-uuid", SUCCEEDED);
 
-	private RabbitTemplate rabbitTemplate;
+		ObjectMapper mapper = new ObjectMapper();
+		String json = mapper.writeValueAsString(event);
 
-	public RabbitValidationRequestNotifier(RabbitTemplate rabbitTemplate) {
-		this.rabbitTemplate = rabbitTemplate;
-	}
+		ValidationFinishedEvent valueFromJson = mapper.readValue(json, ValidationFinishedEvent.class);
+
+		assertThat(valueFromJson).usingRecursiveComparison().isEqualTo(event);
 
-	public void sendEvent(ValidationRequestedEvent event) {
-		LOG.info("Sending message: " + event);
-		rabbitTemplate.convertAndSend("foo.bar.baz", event);
 	}
 
 }
diff --git a/xplan-core/xplan-core-validator-events/src/test/java/de/latlon/core/validator/events/ValidationRequestedEventTest.java b/xplan-core/xplan-core-validator-events/src/test/java/de/latlon/core/validator/events/ValidationRequestedEventTest.java
index cb7db7d09d..f00c4d20ee 100644
--- a/xplan-core/xplan-core-validator-events/src/test/java/de/latlon/core/validator/events/ValidationRequestedEventTest.java
+++ b/xplan-core/xplan-core-validator-events/src/test/java/de/latlon/core/validator/events/ValidationRequestedEventTest.java
@@ -29,6 +29,8 @@ import org.junit.jupiter.api.Test;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 
+import de.latlon.core.validator.events.ValidationRequestedEvent.MediaType;
+import de.latlon.core.validator.events.ValidationRequestedEvent.OriginFile;
 import de.latlon.xplan.validator.web.shared.ValidationOption;
 import de.latlon.xplan.validator.web.shared.ValidationSettings;
 import de.latlon.xplan.validator.web.shared.ValidationType;
@@ -42,7 +44,8 @@ class ValidationRequestedEventTest {
 		List<ValidationType> validationTypes = Arrays.asList(ValidationType.GEOMETRIC, ValidationType.SYNTACTIC,
 				ValidationType.SEMANTIC);
 		ValidationSettings settings = new ValidationSettings("validationName", validationTypes, extendedOptions);
-		ValidationRequestedEvent event = new ValidationRequestedEvent(settings);
+		ValidationRequestedEvent event = new ValidationRequestedEvent(settings, "xFileName", MediaType.PDF,
+				OriginFile.GML);
 
 		ObjectMapper mapper = new ObjectMapper();
 		String json = mapper.writeValueAsString(event);
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/XPlanboxPublicV1EventTest.java
new file mode 100644
index 0000000000..585943e68d
--- /dev/null
+++ b/xplan-core/xplan-core-validator-events/src/test/java/de/latlon/core/validator/events/v1/XPlanboxPublicV1EventTest.java
@@ -0,0 +1,39 @@
+package de.latlon.core.validator.events.v1;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.Test;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import de.latlon.core.validator.events.v1.XPlanboxPublicV1Event.EventType;
+
+class XPlanboxPublicV1EventTest {
+
+	@Test
+	void jsonSerializeValidationStart() throws Exception {
+		XPlanboxPublicV1Event event = new XPlanboxPublicV1Event(EventType.VALIDATION_START, "uuid1",
+				"start validation");
+
+		ObjectMapper mapper = new ObjectMapper();
+		String json = mapper.writeValueAsString(event);
+
+		String expected = "{\"apiVersion\":\"1.0\",\"eventType\":\"VALIDATION_START\",\"uuid\":\"uuid1\",\"message\":\"start validation\"}";
+
+		assertThat(json).isEqualTo(expected);
+	}
+
+	@Test
+	void jsonSerializeValidationFinished() throws Exception {
+		XPlanboxPublicV1Event event = new XPlanboxPublicV1Event(EventType.VALIDATION_FINISHED, "uuid1",
+				"end validation");
+
+		ObjectMapper mapper = new ObjectMapper();
+		String json = mapper.writeValueAsString(event);
+
+		String expected = "{\"apiVersion\":\"1.0\",\"eventType\":\"VALIDATION_FINISHED\",\"uuid\":\"uuid1\",\"message\":\"end validation\"}";
+
+		assertThat(json).isEqualTo(expected);
+	}
+
+}
diff --git a/xplan-docker/xplan-docker-volume-init/setupVolumes.sh b/xplan-docker/xplan-docker-volume-init/setupVolumes.sh
index 8951de68c4..77a9ef20b4 100755
--- a/xplan-docker/xplan-docker-volume-init/setupVolumes.sh
+++ b/xplan-docker/xplan-docker-volume-init/setupVolumes.sh
@@ -90,8 +90,6 @@ XPLAN_SERVICES_METADATA_URL="${XPLAN_SERVICES_METADATA_URL}"
 
 XPLAN_INIT_INSPIREPLU="${XPLAN_INIT_INSPIREPLU:-disabled}"
 
-XPLAN_S3_PUBLIC_URL="${XPLAN_S3_PUBLIC_URL}"
-
 #############################
 # Update content of volumes #
 #############################
diff --git a/xplan-documentation/xplan-betriebshandbuch/src/main/asciidoc/s3storage.adoc b/xplan-documentation/xplan-betriebshandbuch/src/main/asciidoc/s3storage.adoc
index 01a8f16d37..504fe7be2b 100644
--- a/xplan-documentation/xplan-betriebshandbuch/src/main/asciidoc/s3storage.adoc
+++ b/xplan-documentation/xplan-betriebshandbuch/src/main/asciidoc/s3storage.adoc
@@ -42,13 +42,11 @@ XPLAN_S3_SECRET_ACCESS_KEY=MY_SECRET_KEY <2>
 XPLAN_S3_BUCKET_NAME=mydocumentbucket <3>
 XPLAN_S3_REGION=eu-central-1 <4>
 XPLAN_S3_ENDPOINT=s3.eu-central-1.amazonaws.com <5>
-XPLAN_S3_PUBLIC_URL=http://mydocumentbucket.s3.eu-central-1.amazonaws.com <6>
 ----
 <1> Hier muss der S3 Accesskey gesetzt werden
 <2> Hier muss der S3 Secretkey gesetzt werden
 <3> Hier muss der Name des S3 Bucket für die Begleitdokumente gesetzt werden, hier als Beispiel `mydocumentbucket`
 <4> Hier muss die S3 Region gesetzt werden
 <5> Hier muss die S3 Endpoint URL gesetzt werden
-<6> Hier kann die öffentliche S3 Endpoint URL gesetzt werden (optional), setzt sich aus (3), (4) und (5) zusammen.
 
 NOTE: Für die Aktivierung des S3 Objektspeichers für die Ablage von Begleitdokumenten muss zusätzlich auch die Umgebungsvariable `spring_profiles_active=s3doc` gesetzt werden.
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 d73f9fc46d..cc43ddb716 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
@@ -21,7 +21,7 @@
 package de.latlon.xplanbox.api.dokumente.config;
 
 import com.amazonaws.services.s3.AmazonS3;
-import de.latlon.xplan.manager.storage.s3.S3Storage;
+import de.latlon.xplan.commons.s3.S3Storage;
 import de.latlon.xplan.manager.storage.s3.config.AmazonS3Context;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Value;
@@ -45,7 +45,7 @@ public class S3DocumentContext {
 
 	@Bean
 	public S3Storage documentStorage(AmazonS3 s3Client,
-			@Value("${s3.bucketName:#{environment.XPLAN_S3_BUCKET_NAME}}") String bucketName) {
+			@Value("${xplanbox.s3.bucketName:#{environment.XPLAN_S3_BUCKET_NAME}}") String bucketName) {
 		LOG.info("Instantiate S3Storage to manage documents");
 		return new S3Storage(s3Client, bucketName);
 	}
diff --git a/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/handler/DocumentHandler.java b/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/handler/DocumentHandler.java
index 03a8024602..12adba4616 100644
--- a/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/handler/DocumentHandler.java
+++ b/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/handler/DocumentHandler.java
@@ -21,8 +21,7 @@
 package de.latlon.xplanbox.api.dokumente.handler;
 
 import de.latlon.xplan.core.manager.db.repository.PlanRepository;
-import de.latlon.xplan.manager.database.XPlanDao;
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
+import de.latlon.xplan.commons.s3.StorageException;
 import de.latlon.xplanbox.api.commons.exception.InvalidPlanId;
 import de.latlon.xplanbox.api.commons.exception.InvalidPlanIdSyntax;
 import de.latlon.xplanbox.api.dokumente.exception.InvalidDocument;
diff --git a/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/service/DocumentService.java b/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/service/DocumentService.java
index 83ad260f0d..1b762bfc9e 100644
--- a/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/service/DocumentService.java
+++ b/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/service/DocumentService.java
@@ -20,7 +20,7 @@
  */
 package de.latlon.xplanbox.api.dokumente.service;
 
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
+import de.latlon.xplan.commons.s3.StorageException;
 import de.latlon.xplanbox.api.dokumente.exception.InvalidDocument;
 import de.latlon.xplanbox.api.dokumente.v1.model.Document;
 
diff --git a/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/service/s3/S3DocumentService.java b/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/service/s3/S3DocumentService.java
index 1b7f89cddc..ee34897a6c 100644
--- a/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/service/s3/S3DocumentService.java
+++ b/xplan-dokumente/xplan-dokumente-api/src/main/java/de/latlon/xplanbox/api/dokumente/service/s3/S3DocumentService.java
@@ -21,10 +21,10 @@
 package de.latlon.xplanbox.api.dokumente.service.s3;
 
 import com.amazonaws.services.s3.model.S3ObjectSummary;
-import de.latlon.xplan.manager.storage.s3.S3Metadata;
-import de.latlon.xplan.manager.storage.s3.S3Object;
-import de.latlon.xplan.manager.storage.s3.S3Storage;
-import de.latlon.xplan.manager.wmsconfig.raster.storage.StorageException;
+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.api.dokumente.exception.InvalidDocument;
 import de.latlon.xplanbox.api.dokumente.service.DocumentHeader;
 import de.latlon.xplanbox.api.dokumente.service.DocumentHeaderWithStream;
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 729ded25dc..2d9957d1e2 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
@@ -20,6 +20,18 @@
  */
 package de.latlon.xplanbox.api.manager;
 
+import static de.latlon.xplanbox.api.manager.v1.model.Link.RelEnum.ALTERNATE;
+import static de.latlon.xplanbox.api.manager.v1.model.Link.RelEnum.PLANWERKWMS;
+import static de.latlon.xplanbox.api.manager.v1.model.Link.RelEnum.SELF;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
 import de.latlon.xplan.manager.web.shared.PlanStatus;
 import de.latlon.xplan.manager.web.shared.XPlan;
 import de.latlon.xplan.validator.web.shared.XPlanEnvelope;
@@ -35,18 +47,6 @@ import de.latlon.xplanbox.api.manager.v1.model.PlanStatusEnum;
 import org.apache.http.client.utils.URIBuilder;
 import org.slf4j.Logger;
 
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import static de.latlon.xplanbox.api.manager.v1.model.Link.RelEnum.ALTERNATE;
-import static de.latlon.xplanbox.api.manager.v1.model.Link.RelEnum.PLANWERKWMS;
-import static de.latlon.xplanbox.api.manager.v1.model.Link.RelEnum.SELF;
-import static org.slf4j.LoggerFactory.getLogger;
-
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
  */
@@ -120,11 +120,14 @@ public class PlanInfoBuilder {
 		List<Link> links = new ArrayList<>();
 		URI selfRef = createSelfRef();
 		if (selfRef != null) {
-			Link selfLink = new Link().href(selfRef).rel(SELF).type(selfMediaType).title(xPlan.getName());
+			Link selfLink = (Link) new Link().rel(SELF).href(selfRef).type(selfMediaType).title(xPlan.getName());
 			links.add(selfLink);
 
 			alternateMediaTypes.forEach(mediaType -> {
-				Link alternateLink = new Link().href(selfRef).rel(ALTERNATE).type(mediaType).title(xPlan.getName());
+				Link alternateLink = (Link) new Link().rel(ALTERNATE)
+					.href(selfRef)
+					.type(mediaType)
+					.title(xPlan.getName());
 				links.add(alternateLink);
 			});
 		}
@@ -170,7 +173,7 @@ public class PlanInfoBuilder {
 			pathSegments.add(xPlan.getName().replace("/", ""));
 			uriBuilder.setPathSegments(pathSegments);
 			URI planwerkWmsRef = uriBuilder.build();
-			Link planwerkWmsLink = new Link().href(planwerkWmsRef).rel(PLANWERKWMS).title(xPlan.getName());
+			Link planwerkWmsLink = (Link) new Link().rel(PLANWERKWMS).href(planwerkWmsRef).title(xPlan.getName());
 			return planwerkWmsLink;
 		}
 		catch (URISyntaxException e) {
diff --git a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v1/model/Link.java b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v1/model/Link.java
index f787e7788b..8264554856 100644
--- a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v1/model/Link.java
+++ b/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/v1/model/Link.java
@@ -20,18 +20,17 @@
  */
 package de.latlon.xplanbox.api.manager.v1.model;
 
+import java.util.Objects;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 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;
-import java.net.URI;
-import java.util.Objects;
 
 /**
  * Datatype for Link. A Link to a resource related to the resource such as XPlanWerkWMS or
@@ -44,14 +43,11 @@ import java.util.Objects;
 		date = "2020-08-28T13:42:47.160+02:00[Europe/Berlin]")
 @XmlRootElement
 @XmlAccessorType(XmlAccessType.FIELD)
-public class Link {
-
-	private @Valid URI href;
+public class Link extends AbstractLink {
 
 	public enum RelEnum {
 
-		SELF(String.valueOf("self")), ALTERNATE(String.valueOf("alternate")),
-		PLANWERKWMS(String.valueOf("planwerkwms"));
+		SELF("self"), ALTERNATE("alternate"), PLANWERKWMS("planwerkwms");
 
 		private String value;
 
@@ -83,36 +79,6 @@ public class Link {
 
 	private @Valid RelEnum rel;
 
-	private @Valid String type;
-
-	private @Valid String hreflang;
-
-	private @Valid String title;
-
-	private @Valid Integer length;
-
-	/**
-	 *
-	 **/
-	public Link href(URI href) {
-		this.href = href;
-		return this;
-	}
-
-	@Schema(example = "https://xplanbox.lat-lon.de/xmanager/api/v1/plan/123", required = true)
-	@JsonProperty("href")
-	@NotNull
-	public URI getHref() {
-		return href;
-	}
-
-	public void setHref(URI href) {
-		this.href = href;
-	}
-
-	/**
-	 *
-	 **/
 	public Link rel(RelEnum rel) {
 		this.rel = rel;
 		return this;
@@ -128,95 +94,21 @@ public class Link {
 		this.rel = rel;
 	}
 
-	/**
-	 *
-	 **/
-	public Link type(String type) {
-		this.type = type;
-		return this;
-	}
-
-	@Schema(example = "application/json")
-	@JsonProperty("type")
-	public String getType() {
-		return type;
-	}
-
-	public void setType(String type) {
-		this.type = type;
-	}
-
-	/**
-	 *
-	 **/
-	public Link hreflang(String hreflang) {
-		this.hreflang = hreflang;
-		return this;
-	}
-
-	@Schema(example = "en")
-	@JsonProperty("hreflang")
-	public String getHreflang() {
-		return hreflang;
-	}
-
-	public void setHreflang(String hreflang) {
-		this.hreflang = hreflang;
-	}
-
-	/**
-	 *
-	 **/
-	public Link title(String title) {
-		this.title = title;
-		return this;
-	}
-
-	@Schema(example = "Othmarschen 3, Hamburg")
-	@JsonProperty("title")
-	public String getTitle() {
-		return title;
-	}
-
-	public void setTitle(String title) {
-		this.title = title;
-	}
-
-	/**
-	 *
-	 **/
-	public Link length(Integer length) {
-		this.length = length;
-		return this;
-	}
-
-	@Schema
-	@JsonProperty("length")
-	public Integer getLength() {
-		return length;
-	}
-
-	public void setLength(Integer length) {
-		this.length = length;
-	}
-
 	@Override
-	public boolean equals(java.lang.Object o) {
-		if (this == o) {
+	public boolean equals(Object o) {
+		if (this == o)
 			return true;
-		}
-		if (o == null || getClass() != o.getClass()) {
+		if (o == null || getClass() != o.getClass())
+			return false;
+		if (!super.equals(o))
 			return false;
-		}
 		Link link = (Link) o;
-		return Objects.equals(this.href, link.href) && Objects.equals(this.rel, link.rel)
-				&& Objects.equals(this.type, link.type) && Objects.equals(this.hreflang, link.hreflang)
-				&& Objects.equals(this.title, link.title) && Objects.equals(this.length, link.length);
+		return rel == link.rel;
 	}
 
 	@Override
 	public int hashCode() {
-		return Objects.hash(href, rel, type, hreflang, title, length);
+		return Objects.hash(super.hashCode(), rel);
 	}
 
 	@Override
@@ -224,25 +116,14 @@ public class Link {
 		StringBuilder sb = new StringBuilder();
 		sb.append("class Link {\n");
 
-		sb.append("    href: ").append(toIndentedString(href)).append("\n");
+		sb.append("    href: ").append(toIndentedString(getHref())).append("\n");
 		sb.append("    rel: ").append(toIndentedString(rel)).append("\n");
-		sb.append("    type: ").append(toIndentedString(type)).append("\n");
-		sb.append("    hreflang: ").append(toIndentedString(hreflang)).append("\n");
-		sb.append("    title: ").append(toIndentedString(title)).append("\n");
-		sb.append("    length: ").append(toIndentedString(length)).append("\n");
+		sb.append("    type: ").append(toIndentedString(getType())).append("\n");
+		sb.append("    hreflang: ").append(toIndentedString(getHreflang())).append("\n");
+		sb.append("    title: ").append(toIndentedString(getTitle())).append("\n");
+		sb.append("    length: ").append(toIndentedString(getLength())).append("\n");
 		sb.append("}");
 		return sb.toString();
 	}
 
-	/**
-	 * Convert the given object to string with each line indented by 4 spaces (except the
-	 * first line).
-	 */
-	private String toIndentedString(java.lang.Object o) {
-		if (o == null) {
-			return "null";
-		}
-		return o.toString().replace("\n", "\n    ");
-	}
-
 }
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 fb6b50101f..9492e9ccff 100644
--- a/xplan-manager/xplan-manager-api/src/main/resources/application.properties
+++ b/xplan-manager/xplan-manager-api/src/main/resources/application.properties
@@ -35,3 +35,16 @@ spring.rabbitmq.port=${XPLAN_RABBIT_PORT:5672}
 spring.rabbitmq.username=${XPLAN_RABBIT_USER:guest}
 
 xplanbox.rabbitmq.internal.prefix=${XPLAN_RABBIT_INTERNAL_PREFIX:xplanbox}
+xplanbox.rabbitmq.fanout.topics=none
+xplanbox.rabbitmq.public.fanout=${XPLAN_RABBIT_PUBLIC_FANOUT:}
+xplanbox.rabbitmq.task.topics=none
+
+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.validation.fsdirectory=${XPLAN_FS_DIRECTORY:/tmp/validation}
+xplanbox.validation.profiles=${XPLAN_VALIDATOR_PROFILES:}
+xplanbox.validation.s3.bucketName=${XPLAN_VALIDATION_S3_BUCKET_NAME:validation}
+xplanbox.validation.s3.bucketPublicUrl=${XPLAN_VALIDATION_S3_BUCKET_PUBLIC_URL}
diff --git a/xplan-manager/xplan-manager-web/pom.xml b/xplan-manager/xplan-manager-web/pom.xml
index 7e82215a77..c84776ad06 100644
--- a/xplan-manager/xplan-manager-web/pom.xml
+++ b/xplan-manager/xplan-manager-web/pom.xml
@@ -174,11 +174,6 @@
       <groupId>com.fasterxml.jackson.core</groupId>
       <artifactId>jackson-databind</artifactId>
     </dependency>
-    <dependency>
-      <groupId>com.fasterxml.jackson.core</groupId>
-      <artifactId>jackson-databind</artifactId>
-      <type>jar</type>
-    </dependency>
     <dependency>
       <groupId>com.fasterxml.jackson.dataformat</groupId>
       <artifactId>jackson-dataformat-yaml</artifactId>
diff --git a/xplan-tests/xplan-tests-selenium/README.md b/xplan-tests/xplan-tests-selenium/README.md
index ef4181fb20..186d16d28a 100644
--- a/xplan-tests/xplan-tests-selenium/README.md
+++ b/xplan-tests/xplan-tests-selenium/README.md
@@ -10,7 +10,7 @@ mvn clean integration-test -Psystem-tests -DbaseUrlValidatorWeb=https://xplanbox
 
 ## Ausführung im Docker Container
 
-Die Selenium Tests können in einem Docker Container ausgeführt werden
+Die Tests können in einem Docker Container ausgeführt werden
 
 ```
 docker run --env XPLAN_VALIDATOR_WEB_BASE_URL=... xplanbox/xplan-tests-selenium
@@ -21,6 +21,13 @@ docker run --env XPLAN_VALIDATOR_WEB_BASE_URL=... xplanbox/xplan-tests-selenium
 - `XPLAN_VALIDATOR_WEB_BASE_URL`
 - `XPLAN_VALIDATOR_WEB_USERNAME`
 - `XPLAN_VALIDATOR_WEB_PASSWORD`
+- `SKIP_RABBIT_TESTS`: wenn `true` oder `1` werden die Tests ignoriert, für die eine Verbindung zum RabbitMQ Server benötigt wird.
+- `XPLAN_RABBIT_HOST`: der Host vom RabbitMQ Server (Default: `localhost`)
+- `XPLAN_RABBIT_PORT`: der Port vom RabbitMQ Server (Default: `5672`)
+- `XPLAN_RABBIT_USER`: der Benutzername für die Verbindung zum  RabbitMQ Server (Default: `guest`)
+- `XPLAN_RABBIT_PASSWORD`: das Passwort für die Verbindung zum  RabbitMQ Server (Default: `guest`)
+- `XPLAN_RABBIT_PUBLIC_FANOUT`: der Name vom Fanout Channel (Default: `xplanbox-public-fanout`)
+- `XPLAN_VALIDATORAPI_URL_PUBLIC`: die Url von der validator-api Anwendung (Default: `http://localhost:8085/xplan-validator-api`)
 
 Der Report im PDF Format kann zu einem S3 Bucket hochgeladen werden, dafür müssen folgende Umgebungsvariablen gesetzt werden:
 
diff --git a/xplan-tests/xplan-tests-selenium/pom.xml b/xplan-tests/xplan-tests-selenium/pom.xml
index ab2bf8ab35..2846de24b4 100644
--- a/xplan-tests/xplan-tests-selenium/pom.xml
+++ b/xplan-tests/xplan-tests-selenium/pom.xml
@@ -1,4 +1,6 @@
-<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <artifactId>xplan-tests-selenium</artifactId>
 
@@ -47,6 +49,15 @@
       <artifactId>assertj-core</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>io.github.openfeign</groupId>
+      <artifactId>feign-jackson</artifactId>
+      <version>13.3</version>
+    </dependency>
+    <dependency>
+      <groupId>com.rabbitmq</groupId>
+      <artifactId>amqp-client</artifactId>
+    </dependency>
   </dependencies>
 
   <build>
@@ -64,10 +75,10 @@
     <profile>
       <id>system-tests</id>
       <properties>
-        <baseUrlValidatorWeb />
+        <baseUrlValidatorWeb/>
         <maven.test.skip>false</maven.test.skip>
-        <password />
-        <username />
+        <password/>
+        <username/>
       </properties>
       <build>
         <plugins>
@@ -111,11 +122,15 @@
                         <files>
                           <file>
                             <source>../pom.xml</source>
-                            <destName>xplan-tests-pom.xml</destName>
+                            <destName>
+                              xplan-tests-pom.xml
+                            </destName>
                           </file>
                           <file>
                             <source>../../pom.xml</source>
-                            <destName>xplanbox-pom.xml</destName>
+                            <destName>
+                              xplanbox-pom.xml
+                            </destName>
                           </file>
                         </files>
                       </inline>
diff --git a/xplan-tests/xplan-tests-selenium/runAllSeleniumTests.sh b/xplan-tests/xplan-tests-selenium/runAllSeleniumTests.sh
index fa2e91a834..3528bccf1a 100755
--- a/xplan-tests/xplan-tests-selenium/runAllSeleniumTests.sh
+++ b/xplan-tests/xplan-tests-selenium/runAllSeleniumTests.sh
@@ -38,6 +38,7 @@ function waitForRightVersion() {
 
 echo "Waiting for services with git revision $GIT_REVISION:"
 waitForRightVersion $XPLAN_VALIDATOR_WEB_BASE_URL/version.txt
+waitForRightVersion $XPLAN_VALIDATORAPI_URL_PUBLIC/xvalidator/version.txt
 
 # start virtual buffer
 Xvfb :0 -screen 0 1024x768x24 &
diff --git a/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/validator/rabbit/ValidationPublicEventsIT.java b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/validator/rabbit/ValidationPublicEventsIT.java
new file mode 100644
index 0000000000..f75326822d
--- /dev/null
+++ b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/validator/rabbit/ValidationPublicEventsIT.java
@@ -0,0 +1,219 @@
+package de.latlon.xplanbox.tests.validator.rabbit;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.stream.Collectors;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable;
+
+import com.rabbitmq.client.Channel;
+import com.rabbitmq.client.Connection;
+import com.rabbitmq.client.ConnectionFactory;
+import com.rabbitmq.client.DeliverCallback;
+
+import de.latlon.xplanbox.tests.validator.rabbit.ValidatorApiV2.StatusResponse;
+import de.latlon.xplanbox.tests.validator.rabbit.ValidatorApiV2.ValidateResponse;
+import feign.Client;
+import feign.Feign;
+import feign.RequestTemplate;
+import feign.codec.EncodeException;
+import feign.codec.Encoder;
+import feign.jackson.JacksonDecoder;
+
+@DisabledIfEnvironmentVariable(named = "SKIP_RABBIT_TESTS", matches = "(1|true)")
+class ValidationPublicEventsIT {
+
+	private List<String> receivedPublicEvents = Collections.synchronizedList(new ArrayList<>());
+
+	record TestConfig(String apiBaseUrl, String rabbitHost, int rabbitPort, String rabbitUsername,
+			String rabbitPassword, String publicFanoutQueueName) {
+	}
+
+	static TestConfig getTestConfig() {
+		String apiBaseUrl = getEnv("XPLAN_VALIDATORAPI_URL_PUBLIC", "http://localhost:8085/xplan-validator-api");
+		String rabbitHost = getEnv("XPLAN_RABBIT_HOST", "localhost");
+		int rabbitPort = Integer.parseInt(getEnv("XPLAN_RABBIT_PORT", "5672"), 10);
+		String rabbitUsername = getEnv("XPLAN_RABBIT_USER", "guest");
+		String rabbitPassword = getEnv("XPLAN_RABBIT_PASSWORD", "guest");
+		String publicFanoutQueueName = getEnv("XPLAN_RABBIT_PUBLIC_FANOUT", "xplanbox-public-fanout");
+		return new TestConfig(apiBaseUrl, rabbitHost, rabbitPort, rabbitUsername, rabbitPassword,
+				publicFanoutQueueName);
+	}
+
+	private static String getEnv(String key, String defaultValue) {
+		String value = System.getenv(key);
+		if (value == null || value.isBlank()) {
+			value = System.getProperty(key, defaultValue);
+		}
+		return value;
+	}
+
+	private TestConfig testConfig = getTestConfig();
+
+	@Test
+	void validateAndVerifyPublicEvents() throws Exception {
+		ValidatorApiV2 v2Api = Feign.builder() //
+			.client(new Client.Default(getSSLSocketFactory(), getHostnameVerifier()))
+			// .logger(new Logger.ErrorLogger()) //
+			// .logLevel(Level.FULL) //
+			.encoder(new SimpleBodyFileEncoder()) //
+			.decoder(new JacksonDecoder()) //
+			.target(ValidatorApiV2.class, testConfig.apiBaseUrl);
+
+		startRabbitPublicEventsReception();
+
+		Path f = Paths.get(getClass().getResource("/BPlan001_5-4.zip").toURI());
+		ValidateResponse r = v2Api.validate(f);
+
+		assertThat(r.uuid()).isNotBlank();
+		assertThat(r.statusLink()).isNotNull();
+
+		// verify status (probably not yet finished but who knows...)
+		StatusResponse statusResponse = v2Api.status(r.uuid());
+		assertThat(statusResponse.status()).isIn("REQUESTED", "FINISHED"); // ....
+
+		// awaiting 2 events for this uuid
+		List<String> expectedEvents = List.of( //
+				"{\"apiVersion\":\"1.0\",\"eventType\":\"VALIDATION_START\",\"uuid\":\"" + r.uuid()
+						+ "\",\"message\":\"validation started\"}", //
+				"{\"apiVersion\":\"1.0\",\"eventType\":\"VALIDATION_FINISHED\",\"uuid\":\"" + r.uuid()
+						+ "\",\"message\":\"validation finished\"}");
+		waitingIfNeeded(10, () -> assertThat(receivedEventsFor(r.uuid())).isEqualTo(expectedEvents));
+
+		// verify status
+		statusResponse = v2Api.status(r.uuid());
+		assertThat(statusResponse.status()).isEqualTo("FINISHED"); // now surely finished
+
+		System.out.println(receivedPublicEvents);
+	}
+
+	List<String> receivedEventsFor(String uuid) {
+		return receivedPublicEvents.stream() //
+			.filter((it) -> it.contains(uuid)) //
+			.collect(Collectors.toList());
+	}
+
+	private void startRabbitPublicEventsReception() throws Exception {
+		ConnectionFactory factory = new ConnectionFactory();
+		factory.setHost(testConfig.rabbitHost);
+		factory.setPort(testConfig.rabbitPort);
+		factory.setUsername(testConfig.rabbitUsername);
+		factory.setPassword(testConfig.rabbitPassword);
+		Connection connection = factory.newConnection();
+		Channel channel = connection.createChannel();
+
+		String queueName = channel.queueDeclare().getQueue();
+		channel.queueBind(queueName, testConfig.publicFanoutQueueName(), "");
+
+		DeliverCallback deliverCallback = (consumerTag, delivery) -> {
+			String message = new String(delivery.getBody(), "UTF-8");
+			receivedPublicEvents.add(message);
+		};
+		channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {
+		});
+	}
+
+	// SSLSocketFactory
+	// Install the all-trusting trust manager
+	public static SSLSocketFactory getSSLSocketFactory() {
+		try {
+			SSLContext sslContext = SSLContext.getInstance("SSL");
+			sslContext.init(null, getTrustManager(), new SecureRandom());
+			return sslContext.getSocketFactory();
+		}
+		catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	// TrustManager
+	// trust manager that does not validate certificate chains
+	private static TrustManager[] getTrustManager() {
+		TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
+			@Override
+			public void checkClientTrusted(X509Certificate[] chain, String authType) {
+
+			}
+
+			@Override
+			public void checkServerTrusted(X509Certificate[] chain, String authType) {
+
+			}
+
+			@Override
+			public X509Certificate[] getAcceptedIssuers() {
+				return new X509Certificate[] {};
+			}
+		} };
+		return trustAllCerts;
+	}
+
+	// HostnameVerifier
+	public static HostnameVerifier getHostnameVerifier() {
+		HostnameVerifier hostnameVerifier = new HostnameVerifier() {
+			@Override
+			public boolean verify(String s, SSLSession sslSession) {
+				return true;
+			}
+		};
+		return hostnameVerifier;
+	}
+
+	// encode @Param("bodyFile") to request body bytes
+	public static class SimpleBodyFileEncoder implements Encoder {
+
+		public void encode(Object object, Type type, RequestTemplate template) throws EncodeException {
+			@SuppressWarnings("unchecked")
+			Map<String, ?> params = (Map<String, ?>) object;
+			Path file = (Path) params.get("bodyFile");
+			byte[] bytes;
+			try {
+				bytes = Files.readAllBytes(file);
+			}
+			catch (IOException e) {
+				throw new RuntimeException(e);
+			}
+			template.body(bytes, StandardCharsets.UTF_8);
+		}
+
+	}
+
+	private void waitingIfNeeded(int maxWaitInSeconds, Callable<?> callable) throws Exception {
+		long maxWaitTime = System.currentTimeMillis() + 1_000 * maxWaitInSeconds;
+		while (true) {
+			try {
+				callable.call();
+				return;
+			}
+			catch (Throwable t) {
+				if (System.currentTimeMillis() > maxWaitTime) {
+					throw t;
+				}
+				Thread.sleep(1_000);
+			}
+		}
+
+	}
+
+}
diff --git a/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/validator/rabbit/ValidatorApiV2.java b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/validator/rabbit/ValidatorApiV2.java
new file mode 100644
index 0000000000..1f4cc988fb
--- /dev/null
+++ b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/validator/rabbit/ValidatorApiV2.java
@@ -0,0 +1,33 @@
+package de.latlon.xplanbox.tests.validator.rabbit;
+
+import java.nio.file.Path;
+import java.util.List;
+
+import feign.Headers;
+import feign.Param;
+import feign.RequestLine;
+
+/**
+ * Simple interface for the API methods currently tested. All paths relative to
+ * "/xplan-validator-api"
+ */
+public interface ValidatorApiV2 {
+
+	public record StatusResponse(String status, List<Link> links) {
+	}
+
+	public record Link(String expirationDate, String href, String type, String hreflang, String title, String length,
+			String rel) {
+	}
+
+	public record ValidateResponse(String uuid, Link statusLink) {
+	}
+
+	@RequestLine("GET /api/v2/status/{uuid}")
+	StatusResponse status(@Param("uuid") String uuid);
+
+	@RequestLine("POST /api/v2/validate")
+	@Headers("Content-Type: application/zip")
+	ValidateResponse validate(@Param("bodyFile") Path f);
+
+}
\ No newline at end of file
diff --git a/xplan-tests/xplan-tests-soapui/README.md b/xplan-tests/xplan-tests-soapui/README.md
index b9686b6860..b79f364781 100644
--- a/xplan-tests/xplan-tests-soapui/README.md
+++ b/xplan-tests/xplan-tests-soapui/README.md
@@ -8,7 +8,7 @@ Details zu den einzelnen SoapUI TestSuites sind in der [README](src/main/resourc
 
 ```
 mvn clean test -Psystem-tests -DtestFileName=xplan-validator-api-soapui-project.xml \ 
-    -Dendpoint=https://xplanbox.lat-lon.de/xvalidator/api/v1 -Dusername=xplanbox -Dpassword='PWD'
+    -DbaseUrlValidatorApi=https://xplanbox.lat-lon.de -Dusername=xplanbox -Dpassword='PWD'
 ```
 
 ### xplan-manager-api-soapui-project
diff --git a/xplan-tests/xplan-tests-soapui/pom.xml b/xplan-tests/xplan-tests-soapui/pom.xml
index 19c0007390..97b8c1a8e6 100644
--- a/xplan-tests/xplan-tests-soapui/pom.xml
+++ b/xplan-tests/xplan-tests-soapui/pom.xml
@@ -68,11 +68,11 @@
         <baseUrlMapProxy />
         <usernameMapProxy />
         <passwordMapProxy />
+        <baseUrlValidatorApi />
         <username />
         <password />
         <apiKey />
         <jdbcUrl />
-        <endpoint />
       </properties>
       <build>
         <plugins>
@@ -104,9 +104,6 @@
                   <junitReport>true</junitReport>
                   <exportAll>true</exportAll>
                   <testFailIgnore>true</testFailIgnore>
-                  <endpoint>${endpoint}</endpoint>
-                  <username>${username}</username>
-                  <password>${password}</password>
                   <projectProperties>
                     <projectProperty>projectDir=${basedir}/src/main/resources</projectProperty>
                     <value>baseUrlInspirePlu=${baseUrlInspirePlu}</value>
@@ -127,6 +124,7 @@
                     <value>baseUrlMapProxy=${baseUrlMapProxy}</value>
                     <value>usernameMapProxy=${usernameMapProxy}</value>
                     <value>passwordMapProxy=${passwordMapProxy}</value>
+                    <value>baseUrlValidatorApi=${baseUrlValidatorApi}</value>
                     <value>username=${username}</value>
                     <value>password=${password}</value>
                     <value>apiKey=${apiKey}</value>
diff --git a/xplan-tests/xplan-tests-soapui/runAllSoapUiTests.sh b/xplan-tests/xplan-tests-soapui/runAllSoapUiTests.sh
index ae69ef7ebd..6b6121f191 100755
--- a/xplan-tests/xplan-tests-soapui/runAllSoapUiTests.sh
+++ b/xplan-tests/xplan-tests-soapui/runAllSoapUiTests.sh
@@ -69,7 +69,7 @@ mvn test -Psystem-tests -DtestFileName=xplan-manager-api-soapui-project.xml \
     -DjdbcUrl=$JDBC_URL
 
 mvn test -Psystem-tests -DtestFileName=xplan-validator-api-soapui-project.xml \
-    -Dendpoint=$XPLAN_VALIDATOR_API_BASE_URL/xvalidator/api/v1 -Dusername=$XPLAN_VALIDATOR_API_USERNAME -Dpassword=$XPLAN_VALIDATOR_API_PASSWORD
+    -DbaseUrlValidatorApi=$XPLAN_VALIDATOR_API_BASE_URL -Dusername=$XPLAN_VALIDATOR_API_USERNAME -Dpassword=$XPLAN_VALIDATOR_API_PASSWORD
 
 if [ -z ${XPLAN_DOKUMENTE_API_BASE_URL+x} ];
 then
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 7657184eee..21fc65c9bf 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
@@ -24,6 +24,7 @@
     <con:settings/>
     <con:definitionCache type="TEXT" rootPart=""/>
     <con:endpoints>
+      <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
       <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
       <con:endpoint>https://xplanbox.lat-lon.de/xvalidator/api/v1</con:endpoint>
     </con:endpoints>
@@ -52,16 +53,28 @@ OpenAPI document</con:description>
           <con:params/>
           <con:element>html</con:element>
         </con:representation>
+        <con:representation type="FAULT">
+          <con:mediaType>text/html;charset=utf-8</con:mediaType>
+          <con:status>404</con:status>
+          <con:params/>
+          <con:element>html</con:element>
+        </con:representation>
+        <con:representation type="FAULT">
+          <con:mediaType>application/json</con:mediaType>
+          <con:status>404</con:status>
+          <con:params/>
+          <con:element xmlns:v1="http://localhost/xplan-validator-api/xvalidator/api/v1/">v1:Fault</con:element>
+        </con:representation>
         <con:request name="Request 1" id="17005e5b-eacc-4780-bec7-796702b4e0f4" mediaType="application/json">
           <con:settings>
             <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
           </con:settings>
-          <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+          <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
           <con:request/>
           <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/</con:originalUri>
           <con:credentials>
-            <con:username xsi:nil="true"/>
-            <con:password xsi:nil="true"/>
+            <con:username>${#Project#username}</con:username>
+            <con:password>${#Project#password}</con:password>
             <con:domain xsi:nil="true"/>
             <con:selectedAuthProfile>No Authorization</con:selectedAuthProfile>
             <con:preemptive>false</con:preemptive>
@@ -102,12 +115,12 @@ Show system and application configuration</con:description>
           <con:settings>
             <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
           </con:settings>
-          <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+          <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
           <con:request/>
           <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/info</con:originalUri>
           <con:credentials>
-            <con:username xsi:nil="true"/>
-            <con:password xsi:nil="true"/>
+            <con:username>${#Project#username}</con:username>
+            <con:password>${#Project#password}</con:password>
             <con:domain xsi:nil="true"/>
             <con:selectedAuthProfile>No Authorization</con:selectedAuthProfile>
             <con:authType>No Authorization</con:authType>
@@ -678,12 +691,12 @@ Validate XPlanGML or XPlanArchive</con:description>
           <con:settings>
             <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
           </con:settings>
-          <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+          <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
           <con:request/>
           <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
           <con:credentials>
-            <con:username xsi:nil="true"/>
-            <con:password xsi:nil="true"/>
+            <con:username>${#Project#username}</con:username>
+            <con:password>${#Project#password}</con:password>
             <con:domain xsi:nil="true"/>
             <con:selectedAuthProfile>No Authorization</con:selectedAuthProfile>
             <con:authType>No Authorization</con:authType>
@@ -720,7 +733,7 @@ Validate XPlanGML or XPlanArchive</con:description>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="f3ba4686-3a8b-4dc9-8e96-9bc351221c5a" name="Valid HTTP Status Codes">
@@ -846,8 +859,8 @@ Validate XPlanGML or XPlanArchive</con:description>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>No Authorization</con:selectedAuthProfile>
               <con:preemptive>false</con:preemptive>
@@ -871,7 +884,7 @@ Validate XPlanGML or XPlanArchive</con:description>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/info</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="0cc46e02-cf98-4922-b9a0-70051141ecfd" name="Valid HTTP Status Codes">
@@ -908,8 +921,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>No Authorization</con:selectedAuthProfile>
               <con:authType>No Authorization</con:authType>
@@ -932,7 +945,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -941,8 +954,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -980,7 +993,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -1025,8 +1038,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -1064,7 +1077,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -1109,8 +1122,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -1149,7 +1162,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -1194,8 +1207,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -1234,7 +1247,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -1288,8 +1301,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -1328,7 +1341,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -1373,8 +1386,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -1413,7 +1426,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -1458,8 +1471,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -1498,7 +1511,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -1570,8 +1583,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -1614,7 +1627,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -1659,8 +1672,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -1699,7 +1712,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -1744,8 +1757,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -1783,7 +1796,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -1828,8 +1841,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -1867,7 +1880,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -1876,8 +1889,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -1916,7 +1929,7 @@ assert json.version != null</scriptText>
             <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>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -1961,8 +1974,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -2000,7 +2013,7 @@ assert json.version != null</scriptText>
             <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>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -2027,8 +2040,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -2066,7 +2079,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;entry key="Accept" value="text/xml" xmlns="http://eviware.com/soapui/config"/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -2093,8 +2106,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -2132,7 +2145,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;entry key="Accept" value="application/pdf" xmlns="http://eviware.com/soapui/config"/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -2148,8 +2161,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -2187,7 +2200,7 @@ assert json.version != null</scriptText>
             <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>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -2196,8 +2209,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -2235,7 +2248,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -2289,8 +2302,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -2328,7 +2341,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -2382,8 +2395,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -2421,7 +2434,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -2484,8 +2497,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -2523,7 +2536,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -2586,8 +2599,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -2625,7 +2638,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -2688,8 +2701,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -2727,7 +2740,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -2772,8 +2785,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -2811,7 +2824,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -2856,8 +2869,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -2895,7 +2908,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -2904,8 +2917,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -2944,7 +2957,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;entry key="Accept" value="application/pdf" xmlns="http://eviware.com/soapui/config"/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -2953,8 +2966,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -2993,7 +3006,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -3002,8 +3015,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -3041,7 +3054,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -3095,8 +3108,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -3136,7 +3149,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -3208,8 +3221,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -3249,7 +3262,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -3312,8 +3325,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -3351,7 +3364,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -3367,8 +3380,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -3406,7 +3419,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -3469,8 +3482,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -3509,7 +3522,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -3581,8 +3594,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -3620,7 +3633,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -3701,8 +3714,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -3741,7 +3754,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -3804,8 +3817,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -3844,7 +3857,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -3916,8 +3929,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -3955,7 +3968,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="7d16e282-0f06-406d-9b34-d11a52136ce3" name="Valid HTTP Status Codes">
@@ -3964,8 +3977,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -4012,7 +4025,7 @@ assert json.version != null</scriptText>
             <con:settings>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/info</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="79bf32cf-1071-4e79-ba39-ea58115c33a0" name="Valid HTTP Status Codes">
@@ -4066,8 +4079,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>No Authorization</con:selectedAuthProfile>
               <con:authType>No Authorization</con:authType>
@@ -4106,7 +4119,7 @@ assert json.version != null</scriptText>
               <con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting>
             </con:settings>
             <con:encoding>UTF-8</con:encoding>
-            <con:endpoint>http://localhost:8085/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+            <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
             <con:request/>
             <con:originalUri>http://localhost/xplan-validator-api/xvalidator/api/v1/validate</con:originalUri>
             <con:assertion type="Valid HTTP Status Codes" id="5f4dcada-c13f-4671-84c1-8a94197dfc67" name="Valid HTTP Status Codes">
@@ -4151,8 +4164,8 @@ assert json.version != null</scriptText>
               </con:configuration>
             </con:assertion>
             <con:credentials>
-              <con:username xsi:nil="true"/>
-              <con:password xsi:nil="true"/>
+              <con:username>${#Project#username}</con:username>
+              <con:password>${#Project#password}</con:password>
               <con:domain xsi:nil="true"/>
               <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
               <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
@@ -4203,11 +4216,968 @@ assert json.version != null</scriptText>
       </con:property>
     </con:properties>
   </con:testSuite>
+  <con:testSuite id="fa8cd647-1575-4886-b599-51ecc10029ea" name="XPlanValidatorAPIv2 TestSuite">
+    <con:description>Tests für XPlanValidatorAPI version 2.</con:description>
+    <con:settings/>
+    <con:runType>SEQUENTIAL</con:runType>
+    <con:testCase id="8ba01cec-aea7-4882-b1b0-8d9e4647f2ef" failOnError="false" failTestCaseOnErrors="true" keepSession="false" maxResults="0" name="/ TestCase" searchProperties="true" timeout="0" wsrmEnabled="false" wsrmVersion="1.0" wsrmAckTo="" amfAuthorisation="false" amfEndpoint="" amfLogin="" amfPassword="">
+      <con:description>Tests für den "/"-Pfad.</con:description>
+      <con:settings/>
+      <con:testStep type="httprequest" name="GET XX X.X XX openAPI" id="f77d6853-198d-4e77-ad18-72cbf741adde">
+        <con:settings/>
+        <con:config method="GET" xsi:type="con:HttpRequest" id="c41918a7-8619-4507-bb66-c291e018afa5" name="GET XX X.X XX openAPI" 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/></con:setting>
+          </con:settings>
+          <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/api/v2</con:endpoint>
+          <con:request/>
+          <con:assertion type="Valid HTTP Status Codes" id="f3ba4686-3a8b-4dc9-8e96-9bc351221c5a" name="Valid HTTP Status Codes">
+            <con:configuration>
+              <codes>200</codes>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="41304562-7812-4f95-87b1-17cf5354b417" name="openapi">
+            <con:configuration>
+              <path>$.openapi</path>
+              <content>3.0.1</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="fb838b6f-0eaa-45a1-8a43-f87364021182" name="path /">
+            <con:configuration>
+              <path>$.paths./</path>
+              <content>{"get":{"summary":"OpenAPI document","description":"API documentation","operationId":"openApi","responses":{"200":{"description":"successful operation","content":{"application/json":{"schema":{"type":"object"}}}},"406":{"description":"Requested format is not available"}}}}</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="fb838b6f-0eaa-45a1-8a43-f87364021182" name="path /validate X-Filename parameter">
+            <con:configuration>
+              <path>$.paths./validate.post.parameters.[?(@.name == 'X-Filename')]</path>
+              <content>[{"name":"X-Filename","in":"header","description":"Name of the file to be uploaded","schema":{"pattern":"^[A-Za-z0-9.()_\\-]*$","type":"string"},"example":"File names such as xplan.gml, xplan.xml, xplan.zip"}]</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="634b1a88-6df2-49f0-9e23-8babb820f690" name="path /validate name parameter">
+            <con:configuration>
+              <path>$.paths./validate.post.parameters.[?(@.name == 'name')]</path>
+              <content>[{"name":"name","in":"query","description":"Name of the validation","schema":{"pattern":"^[A-Za-z0-9.()_\\-]*$","type":"string"},"example":"xplan-1Pruefbericht_Torstrasse_10_report-4223"}]</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="634b1a88-6df2-49f0-9e23-8babb820f690" name="path /validate skipSemantisch parameter">
+            <con:configuration>
+              <path>$.paths./validate.post.parameters.[?(@.name == 'skipSemantisch')]</path>
+              <content>[{"name":"skipSemantisch","in":"query","description":"skip semantische Validierung","schema":{"type":"boolean","default":false}}]</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="634b1a88-6df2-49f0-9e23-8babb820f690" name="path /validate skipGeometrisch parameter">
+            <con:configuration>
+              <path>$.paths./validate.post.parameters.[?(@.name == 'skipGeometrisch')]</path>
+              <content>[{"name":"skipGeometrisch","in":"query","description":"skip geometrische Validierung","schema":{"type":"boolean","default":false}}]</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="634b1a88-6df2-49f0-9e23-8babb820f690" name="path /validate skipFlaechenschluss parameter">
+            <con:configuration>
+              <path>$.paths./validate.post.parameters.[?(@.name == 'skipFlaechenschluss')]</path>
+              <content>[{"name":"skipFlaechenschluss","in":"query","description":"skip Flaechenschluss Ueberpruefung","schema":{"type":"boolean","default":false}}]</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="634b1a88-6df2-49f0-9e23-8babb820f690" name="path /validate skipGeltungsbereich parameter">
+            <con:configuration>
+              <path>$.paths./validate.post.parameters.[?(@.name == 'skipGeltungsbereich')]</path>
+              <content>[{"name":"skipGeltungsbereich","in":"query","description":"skip Geltungsbereich Ueberpruefung","schema":{"type":"boolean","default":false}}]</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="634b1a88-6df2-49f0-9e23-8babb820f690" name="path /validate skipLaufrichtung parameter">
+            <con:configuration>
+              <path>$.paths./validate.post.parameters.[?(@.name == 'skipLaufrichtung')]</path>
+              <content>[{"name":"skipLaufrichtung","in":"query","description":"skip Laufrichtung Ueberpruefung","schema":{"type":"boolean","default":false}}]</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="634b1a88-6df2-49f0-9e23-8babb820f690" name="path /validate profiles parameter">
+            <con:configuration>
+              <path>$.paths./validate.post.parameters.[?(@.name == 'profiles')]</path>
+              <content>[{"name":"profiles","in":"query","description":"Names of profiles which shall be additionally used for validation","explode":false,"schema":{"type":"array","items":{"type":"string"}}}]</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="634b1a88-6df2-49f0-9e23-8babb820f690" name="schemas ValidationReport externalReferences items type" disabled="true">
+            <con:configuration>
+              <path>$.components.schemas.ValidationReport.properties.externalReferences.items.type</path>
+              <content>string</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="634b1a88-6df2-49f0-9e23-8babb820f690" name="schemas ValidationReport externalReferencesResult items ref" disabled="true">
+            <con:configuration>
+              <path>$.components.schemas.ValidationReport.properties.externalReferencesResult.items.$ref</path>
+              <content>#/components/schemas/ExternalReferenceResult</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Existence Match" id="21d4a0ad-da22-4876-8ecc-ce7ebc245f39" name="schemas DocumentSummary" disabled="true">
+            <con:configuration>
+              <path>$.components.schemas.DocumentSummary</path>
+              <content>true</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}</path>
+              <content>{"get":{"tags":["status"],"summary":"Status of a validation","description":"Returns the status of a validation","operationId":"status","parameters":[{"name":"uuid","in":"path","description":"UUID of the validation","required":true,"schema":{"type":"string"},"example":"0a0cedbc-bf3f-4f1f-bdaf-ea0e52075540"}],"responses":{"200":{"description":"ValidationReport","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationReceipt"}}}},"404":{"description":"Invalid uuid, no validation with the passed uuid found"},"406":{"description":"Requested format is not available"}}}}</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:jmsConfig JMSDeliveryMode="PERSISTENT"/>
+          <con:jmsPropertyConfig/>
+          <con:parameters/>
+        </con:config>
+      </con:testStep>
+      <con:testStep type="httprequest" name="GET XX X.X XX openAPI invalidAcceptHeaderExpectError" id="a7ea3bf5-a395-42f4-8ebf-ef27b6e766c3">
+        <con:settings/>
+        <con:config method="GET" xsi:type="con:HttpRequest" id="c41918a7-8619-4507-bb66-c291e018afa5" name="GET XX X.X XX openAPI invalidAcceptHeaderExpectError" 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="invalid" xmlns="http://eviware.com/soapui/config"/></con:setting>
+          </con:settings>
+          <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/api/v2</con:endpoint>
+          <con:request/>
+          <con:assertion type="Valid HTTP Status Codes" id="f3ba4686-3a8b-4dc9-8e96-9bc351221c5a" name="Valid HTTP Status Codes">
+            <con:configuration>
+              <codes>406</codes>
+            </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:jmsConfig JMSDeliveryMode="PERSISTENT"/>
+          <con:jmsPropertyConfig/>
+          <con:parameters/>
+        </con:config>
+      </con:testStep>
+      <con:properties/>
+    </con:testCase>
+    <con:testCase id="ea696cef-8d32-45ec-9cbf-65b2c190cfb7" failOnError="false" failTestCaseOnErrors="true" keepSession="false" maxResults="0" name="/info TestCase" searchProperties="true" timeout="0" wsrmEnabled="false" wsrmVersion="1.0" wsrmAckTo="" amfAuthorisation="false" amfEndpoint="" amfLogin="" amfPassword="">
+      <con:description>Tests für den "/info"-Pfad.</con:description>
+      <con:settings/>
+      <con:testStep type="httprequest" name="GET XX X.X XX showConfig" id="2b3bc64c-6c0f-4af1-87d0-b486e93aeccc">
+        <con:settings/>
+        <con:config method="GET" xsi:type="con:HttpRequest" id="70d479ab-c344-411e-a79f-167f3f70c0a9" name="GET XX X.X XX showConfig" 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/></con:setting>
+          </con:settings>
+          <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/api/v2/info</con:endpoint>
+          <con:request/>
+          <con:assertion type="Valid HTTP Status Codes" id="0cc46e02-cf98-4922-b9a0-70051141ecfd" name="Valid HTTP Status Codes">
+            <con:configuration>
+              <codes>200</codes>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Existence Match" id="04006561-4031-47bd-9cd2-fb1215076b2d" name="version">
+            <con:configuration>
+              <path>$.version</path>
+              <content>true</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="GroovyScriptAssertion" id="81fc7cf2-d170-45a8-ba3f-26d3c82a741a" name="versionNotNull">
+            <con:configuration>
+              <scriptText>import groovy.json.JsonSlurper
+
+                json = new JsonSlurper().parseText(messageExchange.response.responseContent)
+                assert !(json.isEmpty())
+
+                assert json.version != null</scriptText>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Existence Match" id="d1a2a299-a358-4dcb-b245-b5ce405449b0" name="supportedXPlanGmlVersions">
+            <con:configuration>
+              <path>$.supportedXPlanGmlVersions</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>
+            <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
+            <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
+            <con:preemptive>true</con:preemptive>
+            <con:authType>Preemptive</con:authType>
+          </con:credentials>
+          <con:jmsConfig JMSDeliveryMode="PERSISTENT"/>
+          <con:jmsPropertyConfig/>
+          <con:parameters/>
+        </con:config>
+      </con:testStep>
+      <con:testStep type="httprequest" name="GET XX X.X XX showConfig invalidAcceptHeaderExpectError" id="3f3d2e0c-ee50-454a-968d-322e846f120a">
+        <con:settings/>
+        <con:config method="GET" xsi:type="con:HttpRequest" id="70d479ab-c344-411e-a79f-167f3f70c0a9" name="GET XX X.X XX showConfig invalidAcceptHeaderExpectError" 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="invalid" xmlns="http://eviware.com/soapui/config"/></con:setting>
+          </con:settings>
+          <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/api/v2/info</con:endpoint>
+          <con:request/>
+          <con:assertion type="Valid HTTP Status Codes" id="0cc46e02-cf98-4922-b9a0-70051141ecfd" name="Valid HTTP Status Codes">
+            <con:configuration>
+              <codes>406</codes>
+            </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:jmsConfig JMSDeliveryMode="PERSISTENT"/>
+          <con:jmsPropertyConfig/>
+          <con:parameters/>
+        </con:config>
+      </con:testStep>
+      <con:properties/>
+    </con:testCase>
+    <con:testCase id="6bb3bcfc-8b50-4786-ab61-966e4b29dfb6" failOnError="false" failTestCaseOnErrors="true" keepSession="false" maxResults="0" name="/validate TestCase" searchProperties="true" timeout="0" wsrmEnabled="false" wsrmVersion="1.0" wsrmAckTo="" amfAuthorisation="false" amfEndpoint="" amfLogin="" amfPassword="">
+      <con:description>Tests für den "/validate"-Pfad.</con:description>
+      <con:settings/>
+      <con:testStep type="httprequest" name="POST BP 6.0.2 XX validatePlan" id="12aa68bf-5824-4401-bde6-18535f69548a">
+        <con:settings/>
+        <con:config method="POST" xsi:type="con:HttpRequest" id="aa5ee7a4-a529-48ac-ad3a-eb3064f75a0f" name="POST BP 6.0.2 XX validatePlan" 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/></con:setting>
+          </con:settings>
+          <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/api/v2/validate</con:endpoint>
+          <con:request/>
+          <con:assertion type="Valid HTTP Status Codes" id="047b0265-8e8e-45c2-b4d6-1c67ce5c4a7c" name="Valid HTTP Status Codes">
+            <con:configuration>
+              <codes>200</codes>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Existence Match" id="a14750a4-b6ee-40eb-b83b-6905d92e26ed" name="uuid">
+            <con:configuration>
+              <path>$.uuid</path>
+              <content>true</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Existence Match" id="cca268ea-ed94-467c-9fee-33c8215bf396" name="statusLink">
+            <con:configuration>
+              <path>$.statusLink</path>
+              <content>true</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Existence Match" id="cca268ea-ed94-467c-9fee-33c8215bf396" name="href">
+            <con:configuration>
+              <path>$.statusLink.href</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>
+            <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>BP_6.0.2_valide.zip</con:name>
+            <con:contentType>application/octet-stream</con:contentType>
+            <con:contentId>BP_6.0.2_valide.zip</con:contentId>
+            <con:url>${projectDir}/xplan-validator-api/plans/BP_6.0.2_valide.zip</con:url>
+            <con:id>292d515d-99cd-4aac-99f1-c05d1d4a5851</con:id>
+          </con:attachment>
+          <con:jmsConfig JMSDeliveryMode="PERSISTENT"/>
+          <con:jmsPropertyConfig/>
+          <con:parameters/>
+        </con:config>
+      </con:testStep>
+      <con:testStep type="transfer" name="POST BP 6.0.2 XX validatePlan Property Transfer" id="ad6e933c-44dc-4400-bd4e-61d7493afc36">
+        <con:settings/>
+        <con:config xsi:type="con:PropertyTransfersStep" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+          <con:transfers setNullOnMissingSource="true" transferTextContent="true" failOnError="true" ignoreEmpty="false" transferToAll="false" entitize="false" transferChildNodes="false">
+            <con:name>hrefStatus</con:name>
+            <con:sourceType>Response</con:sourceType>
+            <con:sourceStep>POST BP 6.0.2 XX validatePlan</con:sourceStep>
+            <con:sourcePath>$.statusLink.href</con:sourcePath>
+            <con:targetType>hrefStatus</con:targetType>
+            <con:targetStep>#TestSuite#</con:targetStep>
+            <con:type>JSONPATH</con:type>
+            <con:targetTransferType>JSONPATH</con:targetTransferType>
+            <con:upgraded>true</con:upgraded>
+          </con:transfers>
+        </con:config>
+      </con:testStep>
+      <con:testStep type="httprequest" name="POST BP 6.0.2 XX validatePlan mismatchingContentTypeAndFileType" id="4a261e97-6577-4e32-b3ea-536c2a239621">
+        <con:settings/>
+        <con:config method="POST" xsi:type="con:HttpRequest" id="aa5ee7a4-a529-48ac-ad3a-eb3064f75a0f" name="POST BP 6.0.2 XX validatePlan mismatchingContentTypeAndFileType" postQueryString="false" mediaType="text/xml" 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/></con:setting>
+          </con:settings>
+          <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/api/v2/validate</con:endpoint>
+          <con:request/>
+          <con:assertion type="Valid HTTP Status Codes" id="047b0265-8e8e-45c2-b4d6-1c67ce5c4a7c" name="Valid HTTP Status Codes">
+            <con:configuration>
+              <codes>200</codes>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Existence Match" id="8f708cd5-ffca-4b46-bf7e-080df45e77ba" name="uuid">
+            <con:configuration>
+              <path>$.uuid</path>
+              <content>true</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Existence Match" id="8390a98f-4263-4974-9789-a23a7a134a41" name="statusLink">
+            <con:configuration>
+              <path>$.statusLink</path>
+              <content>true</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Existence Match" id="b53b1dc3-03fc-469b-8934-81e34c1e7043" name="href">
+            <con:configuration>
+              <path>$.statusLink.href</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>
+            <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>BP_6.0.2_valide.zip</con:name>
+            <con:contentType>text/xml</con:contentType>
+            <con:contentId>BP_6.0.2_valide.zip</con:contentId>
+            <con:url>${projectDir}/xplan-validator-api/plans/BP_6.0.2_valide.zip</con:url>
+            <con:id>292d515d-99cd-4aac-99f1-c05d1d4a5851</con:id>
+          </con:attachment>
+          <con:jmsConfig JMSDeliveryMode="PERSISTENT"/>
+          <con:jmsPropertyConfig/>
+          <con:parameters/>
+        </con:config>
+      </con:testStep>
+      <con:testStep type="transfer" name="POST BP 6.0.2 XX validatePlan mismatchingContentTypeAndFileType Property Transfer" id="deb991ae-2746-43e4-95ec-854455d33c8d">
+        <con:settings/>
+        <con:config xsi:type="con:PropertyTransfersStep" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+          <con:transfers setNullOnMissingSource="true" transferTextContent="true" failOnError="true" ignoreEmpty="false" transferToAll="false" entitize="false" transferChildNodes="false">
+            <con:name>hrefStatus2</con:name>
+            <con:sourceType>Response</con:sourceType>
+            <con:sourceStep>POST BP 6.0.2 XX validatePlan mismatchingContentTypeAndFileType</con:sourceStep>
+            <con:sourcePath>$.statusLink.href</con:sourcePath>
+            <con:targetType>hrefStatus2</con:targetType>
+            <con:targetStep>#TestSuite#</con:targetStep>
+            <con:type>JSONPATH</con:type>
+            <con:targetTransferType>JSONPATH</con:targetTransferType>
+            <con:upgraded>true</con:upgraded>
+          </con:transfers>
+        </con:config>
+      </con:testStep>
+      <con:testStep type="httprequest" name="POST BP 6.0.2 XX validatePlan invalidQueryParamExpectError" id="244e9447-3e31-4d44-b521-25bafd92536c">
+        <con:settings/>
+        <con:config method="POST" xsi:type="con:HttpRequest" id="aa5ee7a4-a529-48ac-ad3a-eb3064f75a0f" name="POST BP 6.0.2 XX validatePlan invalidQueryParamExpectError" 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/></con:setting>
+          </con:settings>
+          <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/api/v2/validate</con:endpoint>
+          <con:request/>
+          <con:assertion type="Valid HTTP Status Codes" id="047b0265-8e8e-45c2-b4d6-1c67ce5c4a7c" name="Valid HTTP Status Codes">
+            <con:configuration>
+              <codes>400</codes>
+            </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>BP_6.0.2_valide.zip</con:name>
+            <con:contentType>application/octet-stream</con:contentType>
+            <con:contentId>BP_6.0.2_valide.zip</con:contentId>
+            <con:url>${projectDir}/xplan-validator-api/plans/BP_6.0.2_valide.zip</con:url>
+            <con:id>292d515d-99cd-4aac-99f1-c05d1d4a5851</con:id>
+          </con:attachment>
+          <con:jmsConfig JMSDeliveryMode="PERSISTENT"/>
+          <con:jmsPropertyConfig/>
+          <con:parameters>
+            <con:parameter>
+              <con:name>name</con:name>
+              <con:value>//</con:value>
+              <con:style>QUERY</con:style>
+            </con:parameter>
+          </con:parameters>
+        </con:config>
+      </con:testStep>
+      <con:testStep type="httprequest" name="POST BP 6.0.2 XX validatePlan invalidAcceptHeaderExpectError" id="d6ddd986-409b-45e3-b69f-13f2b9d18210">
+        <con:settings/>
+        <con:config method="POST" xsi:type="con:HttpRequest" id="aa5ee7a4-a529-48ac-ad3a-eb3064f75a0f" name="POST BP 6.0.2 XX validatePlan invalidAcceptHeaderExpectError" 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;entry key="Accept" value="invalid" xmlns="http://eviware.com/soapui/config"/></con:setting>
+          </con:settings>
+          <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/api/v2/validate</con:endpoint>
+          <con:request/>
+          <con:assertion type="Valid HTTP Status Codes" id="047b0265-8e8e-45c2-b4d6-1c67ce5c4a7c" name="Valid HTTP Status Codes">
+            <con:configuration>
+              <codes>406</codes>
+            </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>BP_6.0.2_valide.zip</con:name>
+            <con:contentType>application/octet-stream</con:contentType>
+            <con:contentId>BP_6.0.2_valide.zip</con:contentId>
+            <con:url>${projectDir}/xplan-validator-api/plans/BP_6.0.2_valide.zip</con:url>
+            <con:id>292d515d-99cd-4aac-99f1-c05d1d4a5851</con:id>
+          </con:attachment>
+          <con:jmsConfig JMSDeliveryMode="PERSISTENT"/>
+          <con:jmsPropertyConfig/>
+          <con:parameters/>
+        </con:config>
+      </con:testStep>
+      <con:testStep type="httprequest" name="POST BP 6.0 XX validatePlan unsupportedMediaTypeZipExpectError" id="4e24cbc3-ecdc-48b1-bcd0-eb709b803334">
+        <con:settings/>
+        <con:config method="POST" xsi:type="con:HttpRequest" id="aa5ee7a4-a529-48ac-ad3a-eb3064f75a0f" name="POST BP 6.0 XX validatePlan unsupportedMediaTypeZipExpectError" 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/></con:setting>
+          </con:settings>
+          <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/api/v2/validate</con:endpoint>
+          <con:request/>
+          <con:assertion type="Valid HTTP Status Codes" id="047b0265-8e8e-45c2-b4d6-1c67ce5c4a7c" name="Valid HTTP Status Codes">
+            <con:configuration>
+              <codes>415</codes>
+            </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>BP_6.0.2_valide.zip</con:name>
+            <con:contentType>application/octet-stream</con:contentType>
+            <con:contentId>BP_6.0.2_valide.zip</con:contentId>
+            <con:url>${projectDir}/xplan-validator-api/plans/Blankenese29_Test_60_InvalidContent.zip</con:url>
+            <con:id>292d515d-99cd-4aac-99f1-c05d1d4a5851</con:id>
+          </con:attachment>
+          <con:jmsConfig JMSDeliveryMode="PERSISTENT"/>
+          <con:jmsPropertyConfig/>
+          <con:parameters/>
+        </con:config>
+      </con:testStep>
+      <con:testStep type="httprequest" name="POST BP X.X XX validatePlan unsupportedMediaTypeOdtExpectError" id="59528b98-9523-40ef-8183-6e100065c202">
+        <con:settings/>
+        <con:config method="POST" xsi:type="con:HttpRequest" id="aa5ee7a4-a529-48ac-ad3a-eb3064f75a0f" name="POST BP X.X XX validatePlan unsupportedMediaTypeOdtExpectError" 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/></con:setting>
+          </con:settings>
+          <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/api/v2/validate</con:endpoint>
+          <con:request/>
+          <con:assertion type="Valid HTTP Status Codes" id="047b0265-8e8e-45c2-b4d6-1c67ce5c4a7c" name="Valid HTTP Status Codes">
+            <con:configuration>
+              <codes>415</codes>
+            </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>BP_6.0.2_valide.zip</con:name>
+            <con:contentType>application/octet-stream</con:contentType>
+            <con:contentId>BP_6.0.2_valide.zip</con:contentId>
+            <con:url>${projectDir}/xplan-validator-api/plans/invalidContentType.odt</con:url>
+            <con:id>292d515d-99cd-4aac-99f1-c05d1d4a5851</con:id>
+          </con:attachment>
+          <con:jmsConfig JMSDeliveryMode="PERSISTENT"/>
+          <con:jmsPropertyConfig/>
+          <con:parameters/>
+        </con:config>
+      </con:testStep>
+      <con:properties/>
+    </con:testCase>
+    <con:testCase id="1ac50e96-08c6-4f7f-b28c-b0c00453a683" failOnError="false" failTestCaseOnErrors="true" keepSession="false" maxResults="0" name="/status/{uuid} TestCase" searchProperties="true" timeout="0" wsrmEnabled="false" wsrmVersion="1.0" wsrmAckTo="" amfAuthorisation="false" amfEndpoint="" amfLogin="" amfPassword="">
+      <con:description>Tests für den "/status/{uuid}"-Pfad.</con:description>
+      <con:settings/>
+      <con:testStep type="httprequest" name="GET BP 6.0.2 XX retrieveStatus" id="f6b97694-bf15-4a53-8b89-d854f9bd8680">
+        <con:settings/>
+        <con:config method="GET" xsi:type="con:HttpRequest" id="80a79ed8-fcfd-4604-9220-f7c650063d0c" name="GET BP 6.0.2 XX retrieveStatus" 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/></con:setting>
+          </con:settings>
+          <con:endpoint>${#TestSuite#hrefStatus}</con:endpoint>
+          <con:request/>
+          <con:assertion type="Valid HTTP Status Codes" id="ae2299b3-55a5-4171-b298-0c0fbf353fbb" name="Valid HTTP Status Codes">
+            <con:configuration>
+              <codes>200</codes>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Existence Match" id="9c15ee46-6bc7-4cb2-bca6-6439ca6fdd4f" name="status exists">
+            <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 Match" id="c47301d5-d89e-4a17-8345-4329bf534b29" name="status" disabled="true">
+            <con:configuration>
+              <path>$.status</path>
+              <content>FINISHED</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Existence Match" id="9c15ee46-6bc7-4cb2-bca6-6439ca6fdd4f" name="links">
+            <con:configuration>
+              <path>$.links</path>
+              <content>true</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath RegEx Match" id="79d9689a-c545-4733-bf8d-4b8da83f53a3" name="link[0]" disabled="true">
+            <con:configuration>
+              <path>$.links[0].href</path>
+              <content>true</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+              <regEx>(.*).json|(.*).pdf</regEx>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath RegEx Match" id="79d9689a-c545-4733-bf8d-4b8da83f53a3" name="link[1]" disabled="true">
+            <con:configuration>
+              <path>$.links[1].href</path>
+              <content>true</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+              <regEx>(.*).json|(.*).pdf</regEx>
+            </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:jmsConfig JMSDeliveryMode="PERSISTENT"/>
+          <con:jmsPropertyConfig/>
+          <con:parameters/>
+        </con:config>
+      </con:testStep>
+      <con:testStep type="groovy" name="pollStatus" id="119b8ff3-609c-44dc-895b-0399ac3383e3">
+        <con:settings/>
+        <con:config>
+          <script>import groovy.json.JsonSlurper
+
+def testStepName = "GET BP 6.0.2 XX retrieveStatus"
+def response = testRunner.testCase.getTestStepByName(testStepName).getPropertyValue("Response")
+def json = new JsonSlurper().parseText(response)
+
+if( context.loopIndex == null )
+	context.loopIndex = 0
+
+if( ++context.loopIndex &lt; 20 &amp;&amp; json.status != "FINISHED" ){
+	sleep(1000)
+	testRunner.gotoStepByName(testStepName)
+} else if (context.loopIndex == 20) {
+	context.loopIndex = null
+	assert(false)
+} else {
+	context.loopIndex = null
+}</script>
+        </con:config>
+      </con:testStep>
+      <con:testStep type="groovy" name="transferUrls" id="1504923d-a693-40d9-a8c9-8ec60e856c80">
+        <con:settings/>
+        <con:config>
+          <script>import groovy.json.JsonSlurper
+
+def response = testRunner.testCase.getTestStepByName("GET BP 6.0.2 XX retrieveStatus").getPropertyValue("Response")
+def json = new JsonSlurper().parseText(response)
+
+def hrefJson = json.links.find { it.type == "application/json" }.href
+def hrefPdf = json.links.find { it.type == "application/pdf" }.href
+
+testRunner.testCase.testSuite.setPropertyValue( "reportJson", hrefJson )
+testRunner.testCase.testSuite.setPropertyValue( "reportPdf", hrefPdf )</script>
+        </con:config>
+      </con:testStep>
+      <con:testStep type="httprequest" name="GET BP 6.0.2 XX retrieveStatus mismatchingContentTypeAndFileType" id="3bef223a-0426-4f62-8d72-85dc566f33fb">
+        <con:settings/>
+        <con:config method="GET" xsi:type="con:HttpRequest" id="80a79ed8-fcfd-4604-9220-f7c650063d0c" name="GET BP 6.0.2 XX retrieveStatus mismatchingContentTypeAndFileType" 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/></con:setting>
+          </con:settings>
+          <con:endpoint>${#TestSuite#hrefStatus2}</con:endpoint>
+          <con:request/>
+          <con:assertion type="Valid HTTP Status Codes" id="ae2299b3-55a5-4171-b298-0c0fbf353fbb" name="Valid HTTP Status Codes">
+            <con:configuration>
+              <codes>200</codes>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Existence Match" id="c2e1881a-b3ea-42ae-9576-ccd831867f6a" name="status exists">
+            <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 Match" id="bd70dfd2-7b9c-4737-baca-a3278a5b6fd4" name="status" disabled="true">
+            <con:configuration>
+              <path>$.status</path>
+              <content>FAILED</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <ignoreComments>false</ignoreComments>
+            </con:configuration>
+          </con:assertion>
+          <con:assertion type="JsonPath Match" id="1c25a6b8-17f5-48ea-9e07-eb18352886d7" name="errorMsg" disabled="true">
+            <con:configuration>
+              <path>$.errorMsg</path>
+              <content>Could not read attached file as XPlanGML</content>
+              <allowWildcards>false</allowWildcards>
+              <ignoreNamspaceDifferences>false</ignoreNamspaceDifferences>
+              <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>
+            <con:selectedAuthProfile>Basic</con:selectedAuthProfile>
+            <con:addedBasicAuthenticationTypes>Basic</con:addedBasicAuthenticationTypes>
+            <con:preemptive>true</con:preemptive>
+            <con:authType>Preemptive</con:authType>
+          </con:credentials>
+          <con:jmsConfig JMSDeliveryMode="PERSISTENT"/>
+          <con:jmsPropertyConfig/>
+          <con:parameters/>
+        </con:config>
+      </con:testStep>
+      <con:testStep type="groovy" name="pollStatus2" id="8ca0b5da-0bd9-44d8-aa10-5ee9285b7b34">
+        <con:settings/>
+        <con:config>
+          <script>import groovy.json.JsonSlurper
+
+def testStepName = "GET BP 6.0.2 XX retrieveStatus mismatchingContentTypeAndFileType"
+def response = testRunner.testCase.getTestStepByName(testStepName).getPropertyValue("Response")
+def json = new JsonSlurper().parseText(response)
+
+if( context.loopIndex == null )
+	context.loopIndex = 0
+
+if( ++context.loopIndex &lt; 20 &amp;&amp; json.status != "FAILED" ){
+	sleep(1000)
+	testRunner.gotoStepByName(testStepName)
+} else if (context.loopIndex == 20) {
+	context.loopIndex = null
+	assert(false)
+} else {
+	context.loopIndex = null
+}</script>
+        </con:config>
+      </con:testStep>
+      <con:testStep type="httprequest" name="GET BP 6.0.2 XX retrieveReportJson" id="0255adc3-8e64-4a6a-8127-9e26fc88d5c4" disabled="true">
+        <con:settings/>
+        <con:config method="GET" xsi:type="con:HttpRequest" id="80a79ed8-fcfd-4604-9220-f7c650063d0c" name="GET BP 6.0.2 XX retrieveReportJson" 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/></con:setting>
+          </con:settings>
+          <con:endpoint>${#TestSuite#reportJson}</con:endpoint>
+          <con:request/>
+          <con:assertion type="Valid HTTP Status Codes" id="84472359-c38c-468b-b28a-f03bbd016181" name="Valid HTTP Status Codes">
+            <con:configuration>
+              <codes>200</codes>
+            </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:jmsConfig JMSDeliveryMode="PERSISTENT"/>
+          <con:jmsPropertyConfig/>
+          <con:parameters/>
+        </con:config>
+      </con:testStep>
+      <con:testStep type="httprequest" name="GET BP 6.0.2 XX retrieveReportPdf" id="383e53c7-3a23-4fe2-9481-3c823846806b" disabled="true">
+        <con:settings/>
+        <con:config method="GET" xsi:type="con:HttpRequest" id="80a79ed8-fcfd-4604-9220-f7c650063d0c" name="GET BP 6.0.2 XX retrieveReportPdf" 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/></con:setting>
+          </con:settings>
+          <con:endpoint>${#TestSuite#reportPdf}</con:endpoint>
+          <con:request/>
+          <con:assertion type="Valid HTTP Status Codes" id="84472359-c38c-468b-b28a-f03bbd016181" name="Valid HTTP Status Codes">
+            <con:configuration>
+              <codes>200</codes>
+            </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:jmsConfig JMSDeliveryMode="PERSISTENT"/>
+          <con:jmsPropertyConfig/>
+          <con:parameters/>
+        </con:config>
+      </con:testStep>
+      <con:testStep type="httprequest" name="GET BP 6.0.2 XX retrieveStatus invalidUuidExpectError" id="fe250f45-cf4c-404c-a39d-25b1b4df0012">
+        <con:settings/>
+        <con:config method="GET" xsi:type="con:HttpRequest" id="80a79ed8-fcfd-4604-9220-f7c650063d0c" name="GET BP 6.0.2 XX retrieveStatus invalidUuidExpectError" 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/></con:setting>
+          </con:settings>
+          <con:endpoint>${#Project#baseUrlValidatorApi}/xplan-validator-api/api/v2/status/invalid</con:endpoint>
+          <con:request/>
+          <con:assertion type="Valid HTTP Status Codes" id="ae2299b3-55a5-4171-b298-0c0fbf353fbb" name="Valid HTTP Status Codes">
+            <con:configuration>
+              <codes>404</codes>
+            </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:jmsConfig JMSDeliveryMode="PERSISTENT"/>
+          <con:jmsPropertyConfig/>
+          <con:parameters/>
+        </con:config>
+      </con:testStep>
+      <con:testStep type="httprequest" name="GET BP 6.0.2 XX retrieveStatus invalidAcceptHeaderExpectError" id="dbca65e9-2ba6-4e07-8cd4-20f2bfe20b01">
+        <con:settings/>
+        <con:config method="GET" xsi:type="con:HttpRequest" id="80a79ed8-fcfd-4604-9220-f7c650063d0c" name="GET BP 6.0.2 XX retrieveStatus invalidAcceptHeaderExpectError" 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/xml" xmlns="http://eviware.com/soapui/config"/></con:setting>
+          </con:settings>
+          <con:endpoint>${#TestSuite#hrefStatus}</con:endpoint>
+          <con:request/>
+          <con:assertion type="Valid HTTP Status Codes" id="ae2299b3-55a5-4171-b298-0c0fbf353fbb" name="Valid HTTP Status Codes">
+            <con:configuration>
+              <codes>406</codes>
+            </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:jmsConfig JMSDeliveryMode="PERSISTENT"/>
+          <con:jmsPropertyConfig/>
+          <con:parameters/>
+        </con:config>
+      </con:testStep>
+      <con:properties/>
+    </con:testCase>
+    <con:testCase id="9fd4d5d4-1361-4668-adc4-d026000695b0" failOnError="false" failTestCaseOnErrors="true" keepSession="false" maxResults="0" name="Cleanup Properties" searchProperties="true" timeout="0" wsrmEnabled="false" wsrmVersion="1.0" wsrmAckTo="" amfAuthorisation="false" amfEndpoint="" amfLogin="" amfPassword="">
+      <con:description>Gesetzte Properties werden wieder geleert.</con:description>
+      <con:settings/>
+      <con:testStep type="transfer" name="Property Transfer" id="50852410-a76f-4519-9e59-556d1486eb93">
+        <con:settings/>
+        <con:config xsi:type="con:PropertyTransfersStep" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+          <con:transfers setNullOnMissingSource="true" transferTextContent="true" failOnError="true" ignoreEmpty="false" transferToAll="false" entitize="false" transferChildNodes="false">
+            <con:name>hrefStatus</con:name>
+            <con:sourceType>empty</con:sourceType>
+            <con:sourceStep>#TestCase#</con:sourceStep>
+            <con:targetType>hrefStatus</con:targetType>
+            <con:targetStep>#TestSuite#</con:targetStep>
+            <con:upgraded>true</con:upgraded>
+          </con:transfers>
+          <con:transfers setNullOnMissingSource="true" transferTextContent="true" failOnError="true" ignoreEmpty="false" transferToAll="false" entitize="false" transferChildNodes="false">
+            <con:name>reportJson</con:name>
+            <con:sourceType>empty</con:sourceType>
+            <con:sourceStep>#TestCase#</con:sourceStep>
+            <con:targetType>reportJson</con:targetType>
+            <con:targetStep>#TestSuite#</con:targetStep>
+            <con:upgraded>true</con:upgraded>
+          </con:transfers>
+          <con:transfers setNullOnMissingSource="true" transferTextContent="true" failOnError="true" ignoreEmpty="false" transferToAll="false" entitize="false" transferChildNodes="false">
+            <con:name>reportPdf</con:name>
+            <con:sourceType>empty</con:sourceType>
+            <con:sourceStep>#TestCase#</con:sourceStep>
+            <con:targetType>reportPdf</con:targetType>
+            <con:targetStep>#TestSuite#</con:targetStep>
+            <con:upgraded>true</con:upgraded>
+          </con:transfers>
+          <con:transfers setNullOnMissingSource="true" transferTextContent="true" failOnError="true" disabled="false" entitize="false" ignoreEmpty="false" transferChildNodes="false" transferToAll="false" useXQuery="false">
+            <con:name>hrefStatus2</con:name>
+            <con:sourceType>empty</con:sourceType>
+            <con:sourceStep>#TestCase#</con:sourceStep>
+            <con:sourcePath xsi:nil="true"/>
+            <con:targetType>hrefStatus2</con:targetType>
+            <con:targetStep>#TestSuite#</con:targetStep>
+            <con:targetPath xsi:nil="true"/>
+            <con:type>XPATH</con:type>
+            <con:targetTransferType>XPATH</con:targetTransferType>
+            <con:upgraded>true</con:upgraded>
+          </con:transfers>
+        </con:config>
+      </con:testStep>
+      <con:properties>
+        <con:property>
+          <con:name>empty</con:name>
+          <con:value/>
+        </con:property>
+      </con:properties>
+    </con:testCase>
+    <con:properties>
+      <con:property>
+        <con:name>hrefStatus</con:name>
+        <con:value/>
+      </con:property>
+      <con:property>
+        <con:name>hrefStatus2</con:name>
+        <con:value/>
+      </con:property>
+      <con:property>
+        <con:name>reportJson</con:name>
+        <con:value/>
+      </con:property>
+      <con:property>
+        <con:name>reportPdf</con:name>
+        <con:value/>
+      </con:property>
+    </con:properties>
+  </con:testSuite>
+  <con:endpointStrategy xsi:type="con:DefaultEndpointStrategy" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <con:endpoint mode="COMPLEMENT" username="${#Project#username}" password="${#Project#password}">${#Project#baseUrlValidatorApi}/xplan-validator-api/xvalidator/api/v1</con:endpoint>
+  </con:endpointStrategy>
   <con:properties>
     <con:property>
       <con:name>null</con:name>
       <con:value/>
     </con:property>
+    <con:property>
+      <con:name>baseUrlValidatorApi</con:name>
+      <con:value>http://localhost:8085</con:value>
+    </con:property>
+    <con:property>
+      <con:name>username</con:name>
+      <con:value/>
+    </con:property>
+    <con:property>
+      <con:name>password</con:name>
+      <con:value/>
+    </con:property>
   </con:properties>
   <con:wssContainer/>
   <con:oAuth2ProfileContainer/>
diff --git a/xplan-validator/pom.xml b/xplan-validator/pom.xml
index 2e04209b7f..2815d249ca 100644
--- a/xplan-validator/pom.xml
+++ b/xplan-validator/pom.xml
@@ -13,6 +13,8 @@
   <modules>
     <module>xplan-validator-api</module>
     <module>xplan-validator-config</module>
+    <module>xplan-validator-executor</module>
+    <module>xplan-validator-storage</module>
     <module>xplan-validator-web</module>
   </modules>
 
diff --git a/xplan-validator/xplan-validator-api/Dockerfile b/xplan-validator/xplan-validator-api/Dockerfile
index 1b148be282..355030cf78 100644
--- a/xplan-validator/xplan-validator-api/Dockerfile
+++ b/xplan-validator/xplan-validator-api/Dockerfile
@@ -30,12 +30,11 @@ COPY --from=builder $JMX_EXPORTER_DIR $JMX_EXPORTER_DIR
 
 ENV JAVA_ADDITIONAL_ARG_JAVA17_EXPORTS="--add-exports=java.desktop/com.sun.imageio.spi=ALL-UNNAMED" \
     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 DEEGREE_WORKSPACE_ROOT=/xplanbox/deegree \
-	JAVA_ADDITIONAL_ARG_APP="-Djavax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl -Djts.overlay=ng -Duser.timezone=Europe/Berlin" \
-	XPLANBOX_CONFIG="/xplanbox/xplan-validator-config/"
+    JAVA_ADDITIONAL_ARG_APP="-Djavax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl -Duser.timezone=Europe/Berlin" \
+    XPLANBOX_CONFIG="/xplanbox/xplan-validator-config/"
 
 COPY ${WAR_FILE} /xplanbox/app.war
 COPY run.sh /xplanbox/
diff --git a/xplan-validator/xplan-validator-api/README.md b/xplan-validator/xplan-validator-api/README.md
index 9ebfe953d7..c2510183f3 100644
--- a/xplan-validator/xplan-validator-api/README.md
+++ b/xplan-validator/xplan-validator-api/README.md
@@ -1,9 +1,29 @@
-## xPlanValidatorAPI
+# xPlanValidatorAPI
 
 OpenAPI: #host#/xplan-validator-api/xvalidator/api/v1/
 
+## Development
+
+The application can be started locally with
+
+```
+mvn spring-boot:run -Dspring-boot.run.profiles=dev
+```
+
+(RabbitMQ required on localhost:5672 with credentials guest/guest)
+
+The application starts on port 8085:
+
+- v1 API: http://localhost:8085/xplan-validator-api/xvalidator/api/v1
+
+- v2 API: http://localhost:8085/xplan-validator-api/api/v2
+
 ## Examples with curl 
 
+```
+export XPLAN_VALIDATOR_API_HOST=http://localhost:8085
+```
+
 ### validation
 
 ```
diff --git a/xplan-validator/xplan-validator-api/pom.xml b/xplan-validator/xplan-validator-api/pom.xml
index de6d8d5546..16a78ab6a9 100755
--- a/xplan-validator/xplan-validator-api/pom.xml
+++ b/xplan-validator/xplan-validator-api/pom.xml
@@ -153,6 +153,10 @@
       <groupId>de.latlon.product.xplanbox</groupId>
       <artifactId>xplan-core-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>de.latlon.product.xplanbox</groupId>
+      <artifactId>xplan-validator-storage</artifactId>
+    </dependency>
     <dependency>
       <groupId>de.latlon.product.xplanbox</groupId>
       <artifactId>xplan-core-security</artifactId>
@@ -329,6 +333,10 @@
       <groupId>de.latlon.product.xplanbox</groupId>
       <artifactId>xplan-core-validator-events</artifactId>
     </dependency>
+    <dependency>
+      <groupId>com.amazonaws</groupId>
+      <artifactId>aws-java-sdk-s3</artifactId>
+    </dependency>
   </dependencies>
 
   <profiles>
@@ -336,7 +344,7 @@
       <id>docker</id>
       <properties>
         <docker-image.skip>false</docker-image.skip>
-        <docker-contextTarFile.expectedSizeInMat10pct>85</docker-contextTarFile.expectedSizeInMat10pct>
+        <docker-contextTarFile.expectedSizeInMat10pct>88</docker-contextTarFile.expectedSizeInMat10pct>
       </properties>
       <dependencies>
         <dependency> <!-- to copy jmx exporter stuff from docker image  -->
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/SpringBootApp.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/SpringBootApp.java
index c8388b2511..07c72e0208 100644
--- a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/SpringBootApp.java
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/SpringBootApp.java
@@ -8,32 +8,39 @@
  * 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.validator;
 
+import de.latlon.xplanbox.api.validator.api.v1.ApiV1Config;
+import de.latlon.xplanbox.api.validator.api.v2.ApiV2Config;
+import de.latlon.xplanbox.api.validator.config.ValidatorApiConfiguration;
 import jakarta.servlet.ServletContext;
-import jakarta.servlet.ServletException;
-
+import jakarta.ws.rs.core.Context;
+import org.glassfish.jersey.servlet.ServletContainer;
+import org.glassfish.jersey.servlet.ServletProperties;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration;
 import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
 import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.ServletRegistrationBean;
 import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
 
 @SpringBootApplication
-@ComponentScan(basePackages = { "de.latlon.xplanbox.api.validator.config" })
+@ComponentScan(basePackages = { "de.latlon.xplanbox.api.validator.config",
+		"de.latlon.xplanbox.validator.storage.config", "de.latlon.xplanbox.validator.executor" })
 @EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class })
 public class SpringBootApp extends SpringBootServletInitializer {
 
@@ -51,10 +58,27 @@ public class SpringBootApp extends SpringBootServletInitializer {
 		return application.sources(SpringBootApp.class);
 	}
 
-	@Override
-	public void onStartup(ServletContext servletContext) throws ServletException {
-		// TODO Auto-generated method stub
+	@Bean
+	public ServletRegistrationBean v1config(@Context ServletContext servletContext,
+			ValidatorApiConfiguration validatorApiConfiguration) {
+		ServletRegistrationBean v1config = new ServletRegistrationBean(
+				new ServletContainer(new ApiV1Config(servletContext, validatorApiConfiguration)),
+				"/xvalidator/api/v1/*");
+		v1config.addInitParameter(ServletProperties.JAXRS_APPLICATION_CLASS, ApiV1Config.class.getName());
+		v1config.setName(ApiV1Config.class.getName());
+		v1config.setLoadOnStartup(1);
+		return v1config;
+	}
 
+	@Bean
+	public ServletRegistrationBean v2config(@Context ServletContext servletContext,
+			ValidatorApiConfiguration validatorApiConfiguration) {
+		ServletRegistrationBean v2config = new ServletRegistrationBean(
+				new ServletContainer(new ApiV2Config(servletContext, validatorApiConfiguration)), "/api/v2/*");
+		v2config.addInitParameter(ServletProperties.JAXRS_APPLICATION_CLASS, ApiV2Config.class.getName());
+		v2config.setName(ApiV2Config.class.getName());
+		v2config.setLoadOnStartup(2);
+		return v2config;
 	}
 
 }
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/config/JerseyConfig.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/api/AbstractApiConfig.java
similarity index 70%
rename from xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/config/JerseyConfig.java
rename to xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/api/AbstractApiConfig.java
index 5010b71060..9e6668e3f7 100644
--- a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/config/JerseyConfig.java
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/api/AbstractApiConfig.java
@@ -8,17 +8,19 @@
  * 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.validator.config;
+package de.latlon.xplanbox.api.validator.api;
+
+import java.util.Collections;
 
 import de.latlon.xplanbox.api.commons.ObjectMapperContextResolver;
 import de.latlon.xplanbox.api.commons.converter.StringListConverterProvider;
@@ -26,11 +28,9 @@ import de.latlon.xplanbox.api.commons.exception.ConstraintViolationExceptionMapp
 import de.latlon.xplanbox.api.commons.exception.UnsupportedContentTypeExceptionMapper;
 import de.latlon.xplanbox.api.commons.exception.ValidatorExceptionMapper;
 import de.latlon.xplanbox.api.commons.exception.XPlanApiExceptionMapper;
-import de.latlon.xplanbox.api.commons.openapi.OpenApiFilter;
-import de.latlon.xplanbox.api.validator.v1.DefaultApi;
-import de.latlon.xplanbox.api.validator.v1.InfoApi;
-import de.latlon.xplanbox.api.validator.v1.ValidateApi;
-import io.swagger.v3.oas.integration.SwaggerConfiguration;
+import de.latlon.xplanbox.api.validator.config.ValidatorApiConfiguration;
+import de.latlon.xplanbox.api.validator.exception.ValidationExecutionExceptionMapper;
+import io.swagger.v3.jaxrs2.integration.resources.BaseOpenApiResource;
 import io.swagger.v3.oas.models.ExternalDocumentation;
 import io.swagger.v3.oas.models.OpenAPI;
 import io.swagger.v3.oas.models.info.Contact;
@@ -38,20 +38,10 @@ import io.swagger.v3.oas.models.info.Info;
 import io.swagger.v3.oas.models.info.License;
 import io.swagger.v3.oas.models.servers.Server;
 import io.swagger.v3.oas.models.tags.Tag;
-import org.glassfish.jersey.server.ResourceConfig;
-import org.glassfish.jersey.server.ServerProperties;
-import org.slf4j.Logger;
-import org.springframework.context.annotation.Configuration;
-
 import jakarta.servlet.ServletContext;
-import jakarta.ws.rs.ApplicationPath;
 import jakarta.ws.rs.core.Context;
-import java.util.Collections;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static org.slf4j.LoggerFactory.getLogger;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
 
 /**
  * Application configuration for XPlanValidator REST API. Example mapping for proxy
@@ -62,56 +52,53 @@ import static org.slf4j.LoggerFactory.getLogger;
  *
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
  */
-@ApplicationPath("/xvalidator/api/v1")
-@Configuration
-public class JerseyConfig extends ResourceConfig {
-
-	private static final Logger LOG = getLogger(JerseyConfig.class);
-
-	private static final String APP_PATH = "xvalidator/api/v1";
+public abstract class AbstractApiConfig extends ResourceConfig {
 
-	public JerseyConfig(@Context ServletContext servletContext, ValidatorApiConfiguration validatorApiConfiguration) {
+	public AbstractApiConfig(@Context ServletContext servletContext,
+			ValidatorApiConfiguration validatorApiConfiguration) {
 		property(ServerProperties.WADL_FEATURE_DISABLE, true);
 
 		register(new ObjectMapperContextResolver());
 
-		register(InfoApi.class);
-		register(ValidateApi.class);
+		BaseOpenApiResource openApiResource = createDefaultApi(servletContext, validatorApiConfiguration);
+		register(openApiResource);
+
 		register(ConstraintViolationExceptionMapper.class);
 		register(UnsupportedContentTypeExceptionMapper.class);
+		register(ValidationExecutionExceptionMapper.class);
 		register(ValidatorExceptionMapper.class);
 		register(XPlanApiExceptionMapper.class);
 		register(StringListConverterProvider.class);
+	}
+
+	protected abstract BaseOpenApiResource createDefaultApi(ServletContext servletContext,
+			ValidatorApiConfiguration validatorApiConfiguration);
 
+	protected OpenAPI createOpenAPI(ServletContext servletContext, ValidatorApiConfiguration validatorApiConfiguration,
+			String apiPath) {
 		OpenAPI openApi = new OpenAPI();
-		openApi.setInfo(new Info().title("XPlanValidatorAPI")
-			.version("1.3.0")
-			.description("XPlanValidator REST API")
-			.termsOfService(getTermsOfService(validatorApiConfiguration))
-			.license(new License().name("Apache 2.0").url("http://www.apache.org/licenses/LICENSE-2.0.html")));
+		addInfo(openApi, validatorApiConfiguration);
 		addContact(openApi, validatorApiConfiguration);
-		openApi.servers(servers(servletContext, validatorApiConfiguration));
-		Tag tag = createTag(validatorApiConfiguration);
-		openApi.tags(Collections.singletonList(tag));
-
-		DefaultApi openApiResource = new DefaultApi();
-		SwaggerConfiguration oasConfig = new SwaggerConfiguration().openAPI(openApi)
-			.filterClass(OpenApiFilter.class.getCanonicalName())
-			.prettyPrint(true)
-			.resourcePackages(Stream.of("de.latlon.xplanbox.api.validator.v1").collect(Collectors.toSet()));
-
-		openApiResource.setOpenApiConfiguration(oasConfig);
-		register(openApiResource);
-		LOG.info("XPlanApiValidator successfully initialized");
+		addServers(openApi, servletContext, validatorApiConfiguration, apiPath);
+		addTag(openApi, validatorApiConfiguration);
+		return openApi;
 	}
 
-	private Tag createTag(ValidatorApiConfiguration validatorApiConfiguration) {
+	private void addTag(OpenAPI openApi, ValidatorApiConfiguration validatorApiConfiguration) {
 		Tag tag = new Tag().name("validate").description("Validate XPlanGML documents");
 		if (validatorApiConfiguration != null && validatorApiConfiguration.getDocumentationUrl() != null) {
 			tag.externalDocs(new ExternalDocumentation().description("xPlanBox")
 				.url(validatorApiConfiguration.getDocumentationUrl()));
 		}
-		return tag;
+		openApi.tags(Collections.singletonList(tag));
+	}
+
+	private void addInfo(OpenAPI openApi, ValidatorApiConfiguration validatorApiConfiguration) {
+		openApi.setInfo(new Info().title("XPlanValidatorAPI")
+			.version("1.3.0")
+			.description("XPlanValidator REST API")
+			.termsOfService(getTermsOfService(validatorApiConfiguration))
+			.license(new License().name("Apache 2.0").url("http://www.apache.org/licenses/LICENSE-2.0.html")));
 	}
 
 	private void addContact(OpenAPI openApi, ValidatorApiConfiguration validatorApiConfiguration) {
@@ -121,13 +108,15 @@ public class JerseyConfig extends ResourceConfig {
 		}
 	}
 
-	private List<Server> servers(ServletContext servletContext, ValidatorApiConfiguration validatorApiConfiguration) {
-		String serverUrl = getServerUrl(servletContext, validatorApiConfiguration);
+	private void addServers(OpenAPI openApi, ServletContext servletContext,
+			ValidatorApiConfiguration validatorApiConfiguration, String apiPath) {
+		String serverUrl = getServerUrl(servletContext, validatorApiConfiguration, apiPath);
 		Server server = new Server().url(serverUrl);
-		return Collections.singletonList(server);
+		openApi.servers(Collections.singletonList(server));
 	}
 
-	private String getServerUrl(ServletContext servletContext, ValidatorApiConfiguration validatorApiConfiguration) {
+	private String getServerUrl(ServletContext servletContext, ValidatorApiConfiguration validatorApiConfiguration,
+			String apiPath) {
 		StringBuilder serverUrl = new StringBuilder();
 		if (validatorApiConfiguration != null && validatorApiConfiguration.getApiUrl() != null) {
 			String apiEndpoint = validatorApiConfiguration.getApiUrl().toString();
@@ -138,7 +127,7 @@ public class JerseyConfig extends ResourceConfig {
 		}
 		if (!serverUrl.toString().endsWith("/"))
 			serverUrl.append("/");
-		serverUrl.append(APP_PATH);
+		serverUrl.append(apiPath);
 		return serverUrl.toString();
 	}
 
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/api/v1/ApiV1Config.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/api/v1/ApiV1Config.java
new file mode 100644
index 0000000000..989a1a3b2b
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/api/v1/ApiV1Config.java
@@ -0,0 +1,78 @@
+/*-
+ * #%L
+ * xplan-validator-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%
+ */
+package de.latlon.xplanbox.api.validator.api.v1;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Set;
+
+import de.latlon.xplanbox.api.commons.openapi.OpenApiFilter;
+import de.latlon.xplanbox.api.validator.api.AbstractApiConfig;
+import de.latlon.xplanbox.api.validator.config.ValidatorApiConfiguration;
+import de.latlon.xplanbox.api.validator.v1.DefaultApi;
+import de.latlon.xplanbox.api.validator.v1.InfoApi;
+import de.latlon.xplanbox.api.validator.v1.ValidateApi;
+import io.swagger.v3.jaxrs2.integration.resources.BaseOpenApiResource;
+import io.swagger.v3.oas.integration.SwaggerConfiguration;
+import io.swagger.v3.oas.models.OpenAPI;
+import jakarta.servlet.ServletContext;
+import jakarta.ws.rs.ApplicationPath;
+import jakarta.ws.rs.core.Context;
+import org.slf4j.Logger;
+
+/**
+ * Application configuration for XPlanValidator REST API. Example mapping for proxy
+ * mapping: http://xplanbox.lat-lon.de/xvalidator/api/v1/ ->
+ * http://host:8080/xplan-api-validator/xvalidator/api/v1/ Public address:
+ * http://xplanbox.lat-lon.de/xvalidator/ Internal address:
+ * http://host:8080/xplan-api-validator/xvalidator/
+ *
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ */
+@ApplicationPath("/xvalidator/api/v1")
+public class ApiV1Config extends AbstractApiConfig {
+
+	private static final Logger LOG = getLogger(ApiV1Config.class);
+
+	private static final String APP_PATH = "xvalidator/api/v1";
+
+	public ApiV1Config(@Context ServletContext servletContext, ValidatorApiConfiguration validatorApiConfiguration) {
+		super(servletContext, validatorApiConfiguration);
+
+		register(InfoApi.class);
+		register(ValidateApi.class);
+
+		LOG.info("XPlanApiValidator v1 successfully initialized");
+	}
+
+	public BaseOpenApiResource createDefaultApi(ServletContext servletContext,
+			ValidatorApiConfiguration validatorApiConfiguration) {
+		DefaultApi openApiResourceV1 = new DefaultApi();
+		OpenAPI v1OpenApi = createOpenAPI(servletContext, validatorApiConfiguration, APP_PATH);
+		SwaggerConfiguration oasConfigV1 = new SwaggerConfiguration().openAPI(v1OpenApi)
+			.filterClass(OpenApiFilter.class.getCanonicalName())
+			.prettyPrint(true)
+			.resourcePackages(Set.of("de.latlon.xplanbox.api.validator.v1"));
+		openApiResourceV1.setOpenApiConfiguration(oasConfigV1);
+		return openApiResourceV1;
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/api/v2/ApiV2Config.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/api/v2/ApiV2Config.java
new file mode 100644
index 0000000000..97e57359f2
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/api/v2/ApiV2Config.java
@@ -0,0 +1,81 @@
+/*-
+ * #%L
+ * xplan-validator-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%
+ */
+package de.latlon.xplanbox.api.validator.api.v2;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Set;
+
+import de.latlon.xplanbox.api.validator.api.AbstractApiConfig;
+import de.latlon.xplanbox.api.validator.config.ValidatorApiConfiguration;
+import de.latlon.xplanbox.api.validator.api.v2.ApiV2Filter;
+import de.latlon.xplanbox.api.validator.v2.DefaultApi2;
+import de.latlon.xplanbox.api.validator.v2.InfoApi2;
+import de.latlon.xplanbox.api.validator.v2.StatusApi;
+import de.latlon.xplanbox.api.validator.v2.ValidateApi2;
+import io.swagger.v3.jaxrs2.integration.resources.BaseOpenApiResource;
+import io.swagger.v3.oas.integration.SwaggerConfiguration;
+import io.swagger.v3.oas.models.OpenAPI;
+import jakarta.servlet.ServletContext;
+import jakarta.ws.rs.ApplicationPath;
+import jakarta.ws.rs.core.Context;
+import org.slf4j.Logger;
+
+/**
+ * Application configuration for XPlanValidator REST API. Example mapping for proxy
+ * mapping: http://xplanbox.lat-lon.de/xvalidator/api/v1/ ->
+ * http://host:8080/xplan-api-validator/xvalidator/api/v1/ Public address:
+ * http://xplanbox.lat-lon.de/xvalidator/ Internal address:
+ * http://host:8080/xplan-api-validator/xvalidator/
+ *
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ */
+@ApplicationPath("/api/v2")
+public class ApiV2Config extends AbstractApiConfig {
+
+	private static final Logger LOG = getLogger(ApiV2Config.class);
+
+	private static final String APP_PATH = "api/v2";
+
+	public ApiV2Config(@Context ServletContext servletContext, ValidatorApiConfiguration validatorApiConfiguration) {
+		super(servletContext, validatorApiConfiguration);
+
+		register(InfoApi2.class);
+		register(ValidateApi2.class);
+		register(StatusApi.class);
+
+		LOG.info("XPlanApiValidator v2 successfully initialized");
+	}
+
+	@Override
+	protected BaseOpenApiResource createDefaultApi(ServletContext servletContext,
+			ValidatorApiConfiguration validatorApiConfiguration) {
+		DefaultApi2 openApiResourceV2 = new DefaultApi2();
+		OpenAPI v2OpenApi = createOpenAPI(servletContext, validatorApiConfiguration, APP_PATH);
+		SwaggerConfiguration oasConfigV2 = new SwaggerConfiguration().openAPI(v2OpenApi)
+			.filterClass(ApiV2Filter.class.getCanonicalName())
+			.prettyPrint(true)
+			.resourcePackages(Set.of("de.latlon.xplanbox.api.validator.v2"));
+		openApiResourceV2.setOpenApiConfiguration(oasConfigV2);
+		return openApiResourceV2;
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/api/v2/ApiV2Filter.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/api/v2/ApiV2Filter.java
new file mode 100644
index 0000000000..1311ea46ca
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/api/v2/ApiV2Filter.java
@@ -0,0 +1,22 @@
+package de.latlon.xplanbox.api.validator.api.v2;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import de.latlon.xplanbox.api.commons.openapi.OpenApiFilter;
+
+/**
+ * Filter to keep only v2 Api elements.
+ *
+ * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
+ * @since 8.0
+ */
+public class ApiV2Filter extends OpenApiFilter {
+
+	protected String createNewKey(String path) {
+		Pattern pattern = Pattern.compile("\\/api\\/v[\\d_\\-\\.]*(\\/|)");
+		Matcher matcher = pattern.matcher(path);
+		return matcher.replaceFirst("/");
+	}
+
+}
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 5478f45abc..a416556599 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
@@ -8,18 +8,27 @@
  * 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.validator.config;
 
+import static java.nio.file.Files.createTempDirectory;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
 import de.latlon.xplan.commons.configuration.PropertiesLoader;
 import de.latlon.xplan.commons.configuration.SystemPropertyPropertiesLoader;
 import de.latlon.xplan.manager.web.shared.ConfigurationException;
@@ -39,31 +48,26 @@ import de.latlon.xplan.validator.semantic.profile.SemanticProfilesCreator;
 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.security.config.SecurityContext;
+import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
+import de.latlon.xplanbox.validator.storage.config.AmazonS3Context;
+import de.latlon.xplanbox.validator.storage.filesystem.FileSystemValidationExecutionStorage;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.Profile;
 import org.springframework.core.io.ResourceLoader;
 
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import static java.nio.file.Files.createTempDirectory;
-
 /**
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
  */
 @Configuration
 @ComponentScan(basePackages = { "de.latlon.xplanbox.api.validator.handler", "de.latlon.xplanbox.api.validator.v1" })
-@Import({ SecurityContext.class, ValidatorWmsContext.class })
+@Import({ SecurityContext.class, AmazonS3Context.class })
 public class ApplicationContext {
 
 	@Autowired
@@ -111,7 +115,7 @@ public class ApplicationContext {
 	@Bean
 	public SemanticProfiles semanticProfiles(ValidatorConfiguration validatorConfiguration,
 			PropertiesLoader validatorPropertiesLoader,
-			@Value("#{environment.XPLAN_VALIDATOR_PROFILES}") String activatedProfiles) throws ConfigurationException {
+			@Value("${xplanbox.validation.profiles}") String activatedProfiles) throws ConfigurationException {
 		List<String> activatedProfilesList = activatedProfiles != null ? Arrays.asList(activatedProfiles.split(","))
 				: Collections.emptyList();
 		SemanticProfilesCreator semanticProfilesCreator = new SemanticProfilesCreator(validatorConfiguration,
@@ -155,4 +159,11 @@ public class ApplicationContext {
 		return new ReportWriter();
 	}
 
+	@Bean
+	@Profile("!s3execution")
+	public ValidationExecutionStorage validationExecutionStorage(
+			@Value("${xplanbox.validation.fsdirectory}") Optional<Path> fsExecutionDir) throws IOException {
+		return new FileSystemValidationExecutionStorage(fsExecutionDir);
+	}
+
 }
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/config/RabbitConfiguration.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/config/RabbitConfiguration.java
index 2e1cdec46b..b0bbd5fb88 100644
--- a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/config/RabbitConfiguration.java
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/config/RabbitConfiguration.java
@@ -24,9 +24,10 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 
 import de.latlon.core.validator.events.RabbitEmitterConfig;
+import de.latlon.core.validator.events.RabbitReceiverConfig;
 
 @Configuration
-@Import({ RabbitEmitterConfig.class })
+@Import({ RabbitEmitterConfig.class, RabbitReceiverConfig.class })
 public class RabbitConfiguration {
 
 }
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/exception/InvalidValidationUuid.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/exception/InvalidValidationUuid.java
new file mode 100644
index 0000000000..2d4702c56b
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/exception/InvalidValidationUuid.java
@@ -0,0 +1,44 @@
+/*-
+ * #%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.validator.exception;
+
+import static jakarta.ws.rs.core.Response.Status.NOT_FOUND;
+
+import de.latlon.xplanbox.api.commons.exception.XPlanApiException;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+public class InvalidValidationUuid extends XPlanApiException {
+
+	private static final String EXCEPTION_MESSAGE = "Validation with uuid %s is not available!";
+
+	public InvalidValidationUuid(String uuid) {
+		super(String.format(EXCEPTION_MESSAGE, uuid));
+	}
+
+	@Override
+	public int getStatusCode() {
+		return NOT_FOUND.getStatusCode();
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/exception/ValidationExecutionExceptionMapper.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/exception/ValidationExecutionExceptionMapper.java
new file mode 100644
index 0000000000..8bbc0ca70f
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/exception/ValidationExecutionExceptionMapper.java
@@ -0,0 +1,44 @@
+/*-
+ * #%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.validator.exception;
+
+import de.latlon.xplanbox.validator.storage.ValidationExecutionException;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.ExceptionMapper;
+import jakarta.ws.rs.ext.Provider;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+@Provider
+public class ValidationExecutionExceptionMapper implements ExceptionMapper<ValidationExecutionException> {
+
+	@Override
+	public Response toResponse(ValidationExecutionException exception) {
+		return Response.status(mapStatusCode(exception)).entity(exception.getMessage()).build();
+	}
+
+	private int mapStatusCode(ValidationExecutionException exception) {
+		return exception.getErrorType().getStatusCode();
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/exception/ValidationTimeout.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/exception/ValidationTimeout.java
new file mode 100644
index 0000000000..1017667584
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/exception/ValidationTimeout.java
@@ -0,0 +1,44 @@
+/*-
+ * #%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.validator.exception;
+
+import static jakarta.ws.rs.core.Response.Status.REQUEST_TIMEOUT;
+
+import de.latlon.xplanbox.api.commons.exception.XPlanApiException;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+public class ValidationTimeout extends XPlanApiException {
+
+	private static final String EXCEPTION_MESSAGE = "Timeout of validation %s";
+
+	public ValidationTimeout(String uuid) {
+		super(String.format(EXCEPTION_MESSAGE, uuid));
+	}
+
+	@Override
+	public int getStatusCode() {
+		return REQUEST_TIMEOUT.getStatusCode();
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/handler/AsyncValidationWrapper.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/handler/AsyncValidationWrapper.java
new file mode 100644
index 0000000000..402320200c
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/handler/AsyncValidationWrapper.java
@@ -0,0 +1,102 @@
+/*-
+ * #%L
+ * xplan-validator-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%
+ */
+package de.latlon.xplanbox.api.validator.handler;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import de.latlon.core.validator.events.EventSender;
+import de.latlon.core.validator.events.ValidationFinishedEvent;
+import de.latlon.core.validator.events.ValidationRequestedEvent;
+import de.latlon.xplanbox.api.validator.exception.ValidationTimeout;
+import jakarta.inject.Singleton;
+import org.joda.time.Instant;
+import org.slf4j.Logger;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.stereotype.Component;
+
+@Component
+@Singleton
+public class AsyncValidationWrapper {
+
+	private static final Logger LOG = getLogger(AsyncValidationWrapper.class);
+
+	private final EventSender validationRequestNotifier;
+
+	private final Map<String, Boolean> waitingUuids = Collections.synchronizedMap(new HashMap<>());
+
+	protected AsyncValidationWrapper(EventSender validationRequestNotifier) {
+		this.validationRequestNotifier = validationRequestNotifier;
+	}
+
+	public boolean validate(ValidationRequestedEvent event) throws ValidationTimeout {
+		validationRequestNotifier.sendEvent(event);
+
+		String uuid = event.getUuid();
+		LOG.info("Event sent. Waiting for validation of {}", uuid);
+		waitingUuids.put(uuid, null);
+
+		long maxWaitDate = Long.MAX_VALUE; // TODO: which value would be correct?
+		boolean waitFinished = false;
+		while (!waitFinished) {
+			synchronized (waitingUuids) {
+				try {
+					waitingUuids.wait();
+				}
+				catch (InterruptedException e) {
+					// ignoring
+				}
+			}
+
+			if (waitingUuids.get(uuid) != null) {
+				LOG.info("Finished waiting for validation of {}", uuid);
+				waitFinished = true;
+			}
+			else if (Instant.now().isAfter(maxWaitDate)) {
+				throw new ValidationTimeout(uuid);
+			}
+			else {
+				LOG.info("Still waiting for validation of {}", uuid);
+			}
+		}
+
+		return waitingUuids.remove(uuid);
+	}
+
+	@RabbitListener(queues = "#{internalFanoutQueue.name}")
+	public void someValidationFinished(ValidationFinishedEvent t) {
+		String uuid = t.getUuid();
+		if (waitingUuids.containsKey(uuid)) {
+			LOG.info("Notifying waiting threads for finished validation of {}", uuid);
+			waitingUuids.put(uuid, Boolean.TRUE);
+			synchronized (waitingUuids) {
+				waitingUuids.notifyAll();
+			}
+		}
+		else {
+			LOG.info("No waiting threads for {}. Ignoring", uuid);
+		}
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v1/DefaultApi.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v1/DefaultApi.java
index f2f2f28f69..f1a30ced83 100644
--- a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v1/DefaultApi.java
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v1/DefaultApi.java
@@ -20,10 +20,12 @@
  */
 package de.latlon.xplanbox.api.validator.v1;
 
+import static io.swagger.v3.oas.integration.api.OpenApiContext.OPENAPI_CONTEXT_ID_DEFAULT;
+import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
+
 import io.swagger.v3.jaxrs2.integration.resources.BaseOpenApiResource;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.responses.ApiResponse;
-
 import jakarta.servlet.ServletConfig;
 import jakarta.ws.rs.GET;
 import jakarta.ws.rs.Path;
@@ -34,15 +36,15 @@ import jakarta.ws.rs.core.HttpHeaders;
 import jakarta.ws.rs.core.Response;
 import jakarta.ws.rs.core.UriInfo;
 
-import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
-
 /**
  * Controller class for handling access to the default resource returning the OpenAPI
  * document.
  *
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz</a>
  * @since 4.0
+ * @deprecated since 8.0 use API V2 instead
  */
+@Deprecated
 @Path("/")
 @jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaJAXRSSpecServerCodegen",
 		date = "2020-08-27T12:32:04.497+02:00[Europe/Berlin]")
@@ -63,4 +65,12 @@ public class DefaultApi extends BaseOpenApiResource {
 		return super.getOpenApi(headers, this.config, this.app, uriInfo, APPLICATION_JSON);
 	}
 
+	@Override
+	protected String getContextId(ServletConfig config) {
+		String contextId = super.getContextId(config);
+		if (OPENAPI_CONTEXT_ID_DEFAULT.equals(contextId))
+			return contextId + getClass().getSimpleName();
+		return contextId;
+	}
+
 }
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v1/InfoApi.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v1/InfoApi.java
index 733b6a05bb..01882062c0 100644
--- a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v1/InfoApi.java
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v1/InfoApi.java
@@ -40,7 +40,9 @@ import java.io.IOException;
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz</a>
  * @author <a href="mailto:friebe@lat-lon.de">Torsten Friebe</a>
  * @since 4.0
+ * @deprecated since 8.0 use API V2 instead
  */
+@Deprecated
 @Path("/info")
 @jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaJAXRSSpecServerCodegen",
 		date = "2020-08-27T12:32:04.497+02:00[Europe/Berlin]")
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 0c88a02c1d..f89dec7028 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
@@ -8,31 +8,45 @@
  * 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.validator.v1;
 
-import de.latlon.core.validator.events.ValidationRequestNotifier;
+import static de.latlon.xplan.commons.util.ContentTypeChecker.checkContentTypesOfXPlanArchiveOrGml;
+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 io.swagger.v3.oas.annotations.enums.Explode.FALSE;
+import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
+import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON_TYPE;
+import static jakarta.ws.rs.core.MediaType.APPLICATION_XML;
+import static jakarta.ws.rs.core.MediaType.APPLICATION_XML_TYPE;
+import static jakarta.ws.rs.core.MediaType.TEXT_XML;
+import static jakarta.ws.rs.core.MediaType.TEXT_XML_TYPE;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
 import de.latlon.core.validator.events.ValidationRequestedEvent;
-import de.latlon.xplan.commons.archive.XPlanArchive;
-import de.latlon.xplan.commons.util.UnsupportedContentTypeException;
-import de.latlon.xplan.validator.ValidatorException;
-import de.latlon.xplan.validator.report.ValidatorReport;
 import de.latlon.xplan.validator.web.shared.ValidationSettings;
-import de.latlon.xplanbox.api.commons.ValidationReportBuilder;
-import de.latlon.xplanbox.api.commons.exception.InvalidXPlanGmlOrArchive;
-import de.latlon.xplanbox.api.commons.exception.UnsupportedHeaderValue;
-import de.latlon.xplanbox.api.commons.exception.UnsupportedParameterValue;
+import de.latlon.xplanbox.api.commons.ObjectMapperContextResolver;
 import de.latlon.xplanbox.api.commons.v1.model.ValidationReport;
-import de.latlon.xplanbox.api.validator.handler.ValidationHandler;
+import de.latlon.xplanbox.api.validator.handler.AsyncValidationWrapper;
+import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
 import io.swagger.v3.oas.annotations.Hidden;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
@@ -40,9 +54,6 @@ import io.swagger.v3.oas.annotations.media.Content;
 import io.swagger.v3.oas.annotations.media.Schema;
 import io.swagger.v3.oas.annotations.parameters.RequestBody;
 import io.swagger.v3.oas.annotations.responses.ApiResponse;
-import org.apache.commons.io.FileUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-
 import jakarta.validation.Valid;
 import jakarta.ws.rs.Consumes;
 import jakarta.ws.rs.DefaultValue;
@@ -56,28 +67,7 @@ import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.core.Request;
 import jakarta.ws.rs.core.Response;
 import jakarta.ws.rs.core.Variant;
-import java.io.File;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.file.Files;
-import java.util.List;
-
-import static de.latlon.xplan.commons.util.ContentTypeChecker.checkContentTypesOfXPlanArchiveOrGml;
-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 io.swagger.v3.oas.annotations.enums.Explode.FALSE;
-import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
-import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON_TYPE;
-import static jakarta.ws.rs.core.MediaType.APPLICATION_XML;
-import static jakarta.ws.rs.core.MediaType.APPLICATION_XML_TYPE;
-import static jakarta.ws.rs.core.MediaType.TEXT_XML;
-import static jakarta.ws.rs.core.MediaType.TEXT_XML_TYPE;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * Controller class for handling access to the validate resource.
@@ -85,17 +75,17 @@ import static jakarta.ws.rs.core.MediaType.TEXT_XML_TYPE;
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz</a>
  * @author <a href="mailto:friebe@lat-lon.de">Torsten Friebe</a>
  * @since 4.0
+ * @deprecated since 8.0 use API V2 instead
  */
+@Deprecated
 @Path("/validate")
-@jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaJAXRSSpecServerCodegen",
-		date = "2020-08-26T09:59:16.298+02:00[Europe/Berlin]")
 public class ValidateApi {
 
 	@Autowired
-	private ValidationHandler validationHandler;
+	ValidationExecutionStorage validationExecutionStorage;
 
 	@Autowired
-	private ValidationRequestNotifier validationRequestNotifier;
+	AsyncValidationWrapper validationHandler;
 
 	@POST
 	@Consumes({ "text/xml", "application/gml+xml" })
@@ -157,14 +147,13 @@ public class ValidateApi {
 			@QueryParam("profiles") @Parameter(
 					description = "Names of profiles which shall be additionaly used for validation",
 					explode = FALSE) List<String> profiles)
-			throws IOException, ValidatorException, URISyntaxException, InvalidXPlanGmlOrArchive,
-			UnsupportedContentTypeException, UnsupportedParameterValue, UnsupportedHeaderValue {
+			throws Exception {
 		checkContentTypesOfXPlanArchiveOrGml(body.toPath());
 		String validationName = detectOrCreateValidationName(xFilename, name);
-		XPlanArchive archive = validationHandler.createArchiveFromGml(body, validationName);
 
-		return validate(request, xFilename, validationName, skipSemantisch, skipGeometrisch, skipFlaechenschluss,
-				skipGeltungsbereich, skipLaufrichtung, profiles, archive);
+		return doValidate(body, request, xFilename, validationName, skipSemantisch, skipGeometrisch,
+				skipFlaechenschluss, skipGeltungsbereich, skipLaufrichtung, profiles,
+				ValidationRequestedEvent.OriginFile.GML);
 	}
 
 	@POST
@@ -182,47 +171,55 @@ public class ValidateApi {
 			@QueryParam("profiles") @Parameter(
 					description = "Names of profiles which shall be additionaly used for validation",
 					explode = FALSE) List<String> profiles)
-			throws IOException, ValidatorException, URISyntaxException, InvalidXPlanGmlOrArchive,
-			UnsupportedContentTypeException, UnsupportedParameterValue, UnsupportedHeaderValue {
-		checkContentTypesOfXPlanArchiveOrGml(body.toPath());
-		String validationName = detectOrCreateValidationName(xFilename, name);
-		XPlanArchive archive = validationHandler.createArchiveFromZip(body, validationName);
+			throws Exception {
 
-		return validate(request, xFilename, validationName, skipSemantisch, skipGeometrisch, skipFlaechenschluss,
-				skipGeltungsbereich, skipLaufrichtung, profiles, archive);
+		return doValidate(body, request, xFilename, name, skipSemantisch, skipGeometrisch, skipFlaechenschluss,
+				skipGeltungsbereich, skipLaufrichtung, profiles, ValidationRequestedEvent.OriginFile.ZIP);
 	}
 
-	private Response validate(Request request, String xFileName, String validationName, Boolean skipSemantisch,
+	private Response doValidate(File body, Request request, String xFilename, String name, Boolean skipSemantisch,
 			Boolean skipGeometrisch, Boolean skipFlaechenschluss, Boolean skipGeltungsbereich, Boolean skipLaufrichtung,
-			List<String> profiles, XPlanArchive archive) throws ValidatorException, IOException {
+			List<String> profiles, ValidationRequestedEvent.OriginFile originFile) throws Exception {
+		checkContentTypesOfXPlanArchiveOrGml(body.toPath());
+
+		String uuid = validationExecutionStorage.addPlanToValidate(body.toPath());
+		String validationName = detectOrCreateValidationName(xFilename, name);
 		MediaType mediaType = detectRequestedMediaType(request);
+		final ValidationRequestedEvent.MediaType requestedMediaType = detectValidationEventMediaType(mediaType);
 
 		ValidationSettings settings = createValidationSettings(validationName, skipGeometrisch, skipSemantisch,
 				skipFlaechenschluss, skipGeltungsbereich, skipLaufrichtung, profiles);
 
-		validationRequestNotifier.sendEvent(new ValidationRequestedEvent(settings));
+		ValidationRequestedEvent event = new ValidationRequestedEvent(uuid, settings, xFilename, requestedMediaType,
+				originFile);
 
-		ValidatorReport validatorReport = validationHandler.validate(archive, xFileName, settings);
-		if (APPLICATION_ZIP_TYPE.equals(mediaType)) {
-			java.nio.file.Path report = validationHandler.zipReports(validatorReport);
-			return Response.ok(FileUtils.readFileToByteArray(report.toFile()))
-				.type(APPLICATION_ZIP)
-				.header("Content-Disposition", "attachment; filename=\"" + validationName + ".zip\"")
-				.build();
-		}
-		if (APPLICATION_PDF_TYPE.equals(mediaType)) {
-			java.nio.file.Path report = validationHandler.writePdfReport(validatorReport);
-			return Response.ok(Files.readAllBytes(report))
-				.type(APPLICATION_PDF)
-				.header("Content-Disposition", "attachment; filename=\"" + validationName + ".pdf\"")
+		return validate(event, mediaType);
+	}
+
+	private Response validate(ValidationRequestedEvent validationRequestedEvent, MediaType mediaType) throws Exception {
+
+		ValidationSettings settings = validationRequestedEvent.getSettings();
+		validationHandler.validate(validationRequestedEvent);
+
+		de.latlon.core.validator.events.ValidationRequestedEvent.MediaType requestedMediaType = validationRequestedEvent
+			.getRequestedMediaType();
+		ValidationExecutionStorage.ReportType reportType = ValidationExecutionStorage.ReportType
+			.byFileExtension(requestedMediaType.getFileExtension());
+		byte[] report = validationExecutionStorage.retrieveReport(validationRequestedEvent.getUuid(), reportType);
+		String filename = settings.getValidationName() + requestedMediaType.getFileExtension();
+		// xml not directly supported anymore => parse and convert
+		if (APPLICATION_XML_TYPE.equals(mediaType) || TEXT_XML_TYPE.equals(mediaType)) {
+			ValidationReport validationReport = createReportFileFrom(report);
+			return Response.ok(validationReport) //
+				.type(mediaType) //
+				.header("Content-Disposition", "attachment; filename=\"" + filename + "\"") //
 				.build();
 		}
-		URI wmsUrl = validationHandler.addToWms(archive);
-		ValidationReport validationReport = new ValidationReportBuilder().validatorReport(validatorReport)
-			.filename(xFileName)
-			.wmsUrl(wmsUrl)
+
+		return Response.ok(report) //
+			.type(mediaType) //
+			.header("Content-Disposition", "attachment; filename=\"" + filename + "\"") //
 			.build();
-		return Response.ok(validationReport).build();
 	}
 
 	private MediaType detectRequestedMediaType(Request request) {
@@ -234,4 +231,17 @@ public class ValidateApi {
 		return selectVariant.getMediaType();
 	}
 
+	private static ValidationRequestedEvent.MediaType detectValidationEventMediaType(MediaType mediaType) {
+		if (APPLICATION_ZIP_TYPE.equals(mediaType))
+			return ValidationRequestedEvent.MediaType.ZIP;
+		if (APPLICATION_PDF_TYPE.equals(mediaType))
+			return ValidationRequestedEvent.MediaType.PDF;
+		return ValidationRequestedEvent.MediaType.JSON;
+	}
+
+	private ValidationReport createReportFileFrom(byte[] reportAsJsonInByte) throws IOException {
+		ObjectMapper mapper = new ObjectMapperContextResolver().getContext(ValidationReport.class);
+		return mapper.readValue(reportAsJsonInByte, ValidationReport.class);
+	}
+
 }
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/DefaultApi2.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/DefaultApi2.java
new file mode 100644
index 0000000000..b1961c26c8
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/DefaultApi2.java
@@ -0,0 +1,72 @@
+/*-
+ * #%L
+ * xplan-validator-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%
+ */
+package de.latlon.xplanbox.api.validator.v2;
+
+import static io.swagger.v3.oas.integration.api.OpenApiContext.OPENAPI_CONTEXT_ID_DEFAULT;
+import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
+
+import io.swagger.v3.jaxrs2.integration.resources.BaseOpenApiResource;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import jakarta.servlet.ServletConfig;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.UriInfo;
+
+/**
+ * Controller class for handling access to the default resource returning the OpenAPI
+ * document.
+ *
+ * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
+ * @since 8.0
+ */
+@Path("/")
+public class DefaultApi2 extends BaseOpenApiResource {
+
+	@Context
+	private ServletConfig config;
+
+	@Context
+	private Application app;
+
+	@GET
+	@Produces({ "application/json" })
+	@Operation(summary = "OpenAPI document", description = "API documentation",
+			responses = { @ApiResponse(responseCode = "200", description = "successful operation"),
+					@ApiResponse(responseCode = "406", description = "Requested format is not available") })
+	public Response openApi(@Context HttpHeaders headers, @Context UriInfo uriInfo) throws Exception {
+		return super.getOpenApi(headers, this.config, this.app, uriInfo, APPLICATION_JSON);
+	}
+
+	@Override
+	protected String getContextId(ServletConfig config) {
+		String contextId = super.getContextId(config);
+		if (OPENAPI_CONTEXT_ID_DEFAULT.equals(contextId))
+			return contextId + getClass().getSimpleName();
+		return contextId;
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/InfoApi2.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/InfoApi2.java
new file mode 100644
index 0000000000..07511f5bb3
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/InfoApi2.java
@@ -0,0 +1,62 @@
+/*-
+ * #%L
+ * xplan-validator-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%
+ */
+package de.latlon.xplanbox.api.validator.v2;
+
+import de.latlon.xplanbox.api.commons.v1.model.SystemConfig;
+import de.latlon.xplanbox.api.validator.handler.ConfigHandler;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.Response;
+import java.io.IOException;
+
+/**
+ * Controller class for handling access to the application info resource.
+ *
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz</a>
+ * @author <a href="mailto:friebe@lat-lon.de">Torsten Friebe</a>
+ * @since 4.0
+ */
+@Path("/info")
+public class InfoApi2 {
+
+	@Autowired
+	private ConfigHandler configHandler;
+
+	@GET
+	@Produces({ "application/json" })
+	@Operation(summary = "Show system and application configuration",
+			description = "Returns the system and application configuration",
+			responses = {
+					@ApiResponse(responseCode = "200", description = "successful operation",
+							content = @Content(schema = @Schema(implementation = SystemConfig.class))),
+					@ApiResponse(responseCode = "406", description = "Requested format is not available") })
+	public Response showConfig() throws IOException {
+		return Response.ok().entity(configHandler.describeSystem()).build();
+	}
+
+}
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
new file mode 100644
index 0000000000..0c2a0065fd
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/StatusApi.java
@@ -0,0 +1,83 @@
+/*-
+ * #%L
+ * xplan-validator-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%
+ */
+package de.latlon.xplanbox.api.validator.v2;
+
+import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
+
+import java.net.URISyntaxException;
+
+import de.latlon.xplan.commons.s3.StorageException;
+import de.latlon.xplanbox.api.validator.exception.InvalidValidationUuid;
+import de.latlon.xplanbox.api.validator.v2.model.StatusNotification;
+import de.latlon.xplanbox.api.validator.v2.model.ValidationReceipt;
+import de.latlon.xplanbox.validator.storage.Status;
+import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.Response;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz</a>
+ * @since 8.0
+ */
+@Path("/status")
+public class StatusApi {
+
+	@Autowired
+	private ValidationExecutionStorage validationExecutionStorage;
+
+	@GET
+	@Produces({ "application/json" })
+	@Path("/{uuid}")
+	@Operation(summary = "Status of a validation", description = "Returns the status of a validation",
+			tags = { "status" },
+			responses = {
+					@ApiResponse(responseCode = "200", description = "ValidationReport",
+							content = { @Content(mediaType = APPLICATION_JSON,
+									schema = @Schema(implementation = ValidationReceipt.class)) }),
+					@ApiResponse(responseCode = "404",
+							description = "Invalid uuid, no validation with the passed uuid found"),
+					@ApiResponse(responseCode = "406", description = "Requested format is not available") })
+	public Response status(
+			@PathParam("uuid") @Parameter(description = "UUID of the validation",
+					example = "0a0cedbc-bf3f-4f1f-bdaf-ea0e52075540") String uuid)
+			throws InvalidValidationUuid, StorageException, URISyntaxException {
+		try {
+			Status status = validationExecutionStorage.retrieveStatus(uuid);
+			return Response.ok(StatusNotification.fromStatus(status)).build();
+		}
+		catch (StorageException e) {
+			if (e.getStatusCode() == 404) {
+				throw new InvalidValidationUuid(uuid);
+			}
+			throw e;
+		}
+	}
+
+}
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
new file mode 100644
index 0000000000..0b60497c9e
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/ValidateApi2.java
@@ -0,0 +1,197 @@
+/*-
+ * #%L
+ * xplan-validator-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%
+ */
+package de.latlon.xplanbox.api.validator.v2;
+
+import static de.latlon.xplan.commons.util.ContentTypeChecker.checkContentTypesOfXPlanArchiveOrGml;
+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.validator.v2.model.Link.RelEnum.STATUS;
+import static io.swagger.v3.oas.annotations.enums.Explode.FALSE;
+import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+
+import de.latlon.core.validator.events.EventSender;
+import de.latlon.core.validator.events.ValidationRequestedEvent;
+import de.latlon.xplan.commons.s3.StorageException;
+import de.latlon.xplan.commons.util.UnsupportedContentTypeException;
+import de.latlon.xplan.validator.ValidatorException;
+import de.latlon.xplan.validator.web.shared.ValidationSettings;
+import de.latlon.xplanbox.api.commons.exception.InvalidXPlanGmlOrArchive;
+import de.latlon.xplanbox.api.commons.exception.UnsupportedHeaderValue;
+import de.latlon.xplanbox.api.commons.exception.UnsupportedParameterValue;
+import de.latlon.xplanbox.api.validator.config.ValidatorApiConfiguration;
+import de.latlon.xplanbox.api.validator.v2.model.Link;
+import de.latlon.xplanbox.api.validator.v2.model.ValidationReceipt;
+import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
+import io.swagger.v3.oas.annotations.Hidden;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.parameters.RequestBody;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import jakarta.servlet.ServletContext;
+import jakarta.validation.Valid;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.DefaultValue;
+import jakarta.ws.rs.HeaderParam;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Response;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * Controller class for handling access to the validate resource.
+ *
+ * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
+ * @since 8.0
+ */
+@Path("/validate")
+public class ValidateApi2 {
+
+	@Autowired
+	private ValidationExecutionStorage validationExecutionStorage;
+
+	@Autowired
+	private EventSender validationRequestNotifier;
+
+	@Autowired
+	private ValidatorApiConfiguration validatorApiConfiguration;
+
+	@Context
+	private ServletContext servletContext;
+
+	@POST
+	@Consumes({ "text/xml", "application/gml+xml" })
+	@Produces({ "application/json" })
+	@Operation(summary = "Validate XPlanGML or XPlanArchive", description = "Validates XPlanGML or XPlanArchive file",
+			tags = { "validate" },
+			responses = {
+					@ApiResponse(responseCode = "200", description = "ValidationReport",
+							content = { @Content(mediaType = APPLICATION_JSON,
+									schema = @Schema(implementation = ValidationReceipt.class)) }),
+					@ApiResponse(responseCode = "400", description = "Invalid input"),
+					@ApiResponse(responseCode = "406", description = "Requested format is not available"),
+					@ApiResponse(responseCode = "415",
+							description = "Unsupported media type or content - only xml/gml, zip are accepted; all zip files entries must also match the supported content types for XPlanArchives") },
+			requestBody = @RequestBody(content = {
+					@Content(mediaType = "application/octet-stream",
+							schema = @Schema(type = "string", format = "binary",
+									description = "XPlanGML or XPlanArchive (application/zip) file to upload")),
+					@Content(mediaType = "application/zip",
+							schema = @Schema(type = "string", format = "binary",
+									description = "XPlanGML or XPlanArchive (application/zip) file to upload")),
+					@Content(mediaType = "application/x-zip",
+							schema = @Schema(type = "string", format = "binary",
+									description = "XPlanGML or XPlanArchive (application/zip) file to upload")),
+					@Content(mediaType = "application/x-zip-compressed",
+							schema = @Schema(type = "string", format = "binary",
+									description = "XPlanGML or XPlanArchive (application/zip) file to upload")),
+					@Content(mediaType = "text/xml",
+							schema = @Schema(type = "string", format = "binary", description = "XPlanGML to upload")),
+					@Content(mediaType = "application/gml+xml", schema = @Schema(type = "string", format = "binary",
+							description = "XPlanGML to upload")) }))
+	public Response validate(@Valid File body,
+			@HeaderParam("X-Filename") @Parameter(description = "Name of the file to be uploaded",
+					example = "File names such as xplan.gml, xplan.xml, xplan.zip",
+					schema = @Schema(pattern = SIMPLE_NAME_PATTERN)) String xFilename,
+			@QueryParam("name") @Parameter(description = "Name of the validation",
+					schema = @Schema(pattern = SIMPLE_NAME_PATTERN),
+					example = "xplan-1Pruefbericht_Torstrasse_10_report-4223") String name,
+			@QueryParam("skipSemantisch") @DefaultValue("false") @Parameter(
+					description = "skip semantische Validierung") Boolean skipSemantisch,
+			@QueryParam("skipGeometrisch") @DefaultValue("false") @Parameter(
+					description = "skip geometrische Validierung") Boolean skipGeometrisch,
+			@QueryParam("skipFlaechenschluss") @DefaultValue("false") @Parameter(
+					description = "skip Flaechenschluss Ueberpruefung") Boolean skipFlaechenschluss,
+			@QueryParam("skipGeltungsbereich") @DefaultValue("false") @Parameter(
+					description = "skip Geltungsbereich Ueberpruefung") Boolean skipGeltungsbereich,
+			@QueryParam("skipLaufrichtung") @DefaultValue("false") @Parameter(
+					description = "skip Laufrichtung Ueberpruefung") Boolean skipLaufrichtung,
+			@QueryParam("profiles") @Parameter(
+					description = "Names of profiles which shall be additionally used for validation",
+					explode = FALSE) List<String> profiles)
+			throws IOException, ValidatorException, URISyntaxException, InvalidXPlanGmlOrArchive,
+			UnsupportedContentTypeException, UnsupportedParameterValue, UnsupportedHeaderValue, StorageException {
+		return doValidate(body, xFilename, name, skipSemantisch, skipGeometrisch, skipFlaechenschluss,
+				skipGeltungsbereich, skipLaufrichtung, profiles, ValidationRequestedEvent.OriginFile.GML);
+	}
+
+	@POST
+	@Consumes({ "application/octet-stream", "application/zip", "application/x-zip", "application/x-zip-compressed" })
+	@Produces({ "application/json" })
+	@Hidden
+	public Response validateZip(@Valid File body,
+			@HeaderParam("X-Filename") @Parameter(schema = @Schema(pattern = SIMPLE_NAME_PATTERN)) String xFilename,
+			@QueryParam("name") @Parameter(schema = @Schema(pattern = SIMPLE_NAME_PATTERN)) String name,
+			@QueryParam("skipSemantisch") @DefaultValue("false") Boolean skipSemantisch,
+			@QueryParam("skipGeometrisch") @DefaultValue("false") Boolean skipGeometrisch,
+			@QueryParam("skipFlaechenschluss") @DefaultValue("false") Boolean skipFlaechenschluss,
+			@QueryParam("skipGeltungsbereich") @DefaultValue("false") Boolean skipGeltungsbereich,
+			@QueryParam("skipLaufrichtung") @DefaultValue("false") Boolean skipLaufrichtung,
+			@QueryParam("profiles") @Parameter(
+					description = "Names of profiles which shall be additionally used for validation",
+					explode = FALSE) List<String> profiles)
+			throws IOException, UnsupportedContentTypeException, UnsupportedParameterValue, UnsupportedHeaderValue,
+			StorageException {
+		return doValidate(body, xFilename, name, skipSemantisch, skipGeometrisch, skipFlaechenschluss,
+				skipGeltungsbereich, skipLaufrichtung, profiles, ValidationRequestedEvent.OriginFile.ZIP);
+	}
+
+	private Response doValidate(File body, String xFilename, String name, Boolean skipSemantisch,
+			Boolean skipGeometrisch, Boolean skipFlaechenschluss, Boolean skipGeltungsbereich, Boolean skipLaufrichtung,
+			List<String> profiles, ValidationRequestedEvent.OriginFile originFile) throws IOException,
+			UnsupportedContentTypeException, StorageException, UnsupportedParameterValue, UnsupportedHeaderValue {
+		checkContentTypesOfXPlanArchiveOrGml(body.toPath());
+
+		String uuid = validationExecutionStorage.addPlanToValidate(body.toPath());
+
+		String validationName = detectOrCreateValidationName(xFilename, name);
+		ValidationSettings settings = createValidationSettings(validationName, skipGeometrisch, skipSemantisch,
+				skipFlaechenschluss, skipGeltungsbereich, skipLaufrichtung, profiles);
+
+		validationRequestNotifier.sendEvent(new ValidationRequestedEvent(uuid, settings, xFilename,
+				ValidationRequestedEvent.MediaType.JSON, originFile));
+
+		URI linkToStatus = createLinkToStatus(uuid);
+		Link statusLink = (Link) new Link().rel(STATUS).href(linkToStatus).type("application/json");
+		ValidationReceipt receipt = new ValidationReceipt(uuid, statusLink);
+
+		return Response.ok(receipt).build();
+	}
+
+	private URI createLinkToStatus(String uuid) {
+		URI apiUrl = validatorApiConfiguration.getApiUrl();
+		if (apiUrl == null)
+			return null;
+		return apiUrl.resolve(servletContext.getContextPath() + "/api/v2/status/" + uuid);
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/model/Link.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/model/Link.java
new file mode 100644
index 0000000000..6cfb26d0aa
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/model/Link.java
@@ -0,0 +1,144 @@
+/*-
+ * #%L
+ * xplan-manager-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%
+ */
+package de.latlon.xplanbox.api.validator.v2.model;
+
+import java.util.Date;
+import java.util.Objects;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+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.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Datatype for Link. A Link to a resource related to the resource such as XPlanWerkWMS or
+ * the resource itself.
+ *
+ * @since 4.0
+ */
+@Schema(description = "Link to a resource related to the resource such as XPlanWerkWMS or the resource itself")
+@jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaJAXRSSpecServerCodegen",
+		date = "2020-08-28T13:42:47.160+02:00[Europe/Berlin]")
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Link extends AbstractLink {
+
+	public enum RelEnum {
+
+		STATUS("status"), REPORT("report");
+
+		private String value;
+
+		RelEnum(String v) {
+			value = v;
+		}
+
+		public String value() {
+			return value;
+		}
+
+		@Override
+		@JsonValue
+		public String toString() {
+			return String.valueOf(value);
+		}
+
+		@JsonCreator
+		public static RelEnum fromValue(String value) {
+			for (RelEnum b : RelEnum.values()) {
+				if (b.value.equals(value)) {
+					return b;
+				}
+			}
+			throw new IllegalArgumentException("Unexpected value '" + value + "'");
+		}
+
+	}
+
+	private @Valid RelEnum rel;
+
+	private Date expirationTime;
+
+	public Link rel(RelEnum rel) {
+		this.rel = rel;
+		return this;
+	}
+
+	@Schema(example = "self")
+	@JsonProperty("rel")
+	public RelEnum getRel() {
+		return rel;
+	}
+
+	public void setRel(RelEnum rel) {
+		this.rel = rel;
+	}
+
+	public Date getExpirationTime() {
+		return expirationTime;
+	}
+
+	public void setExpirationTime(Date expirationTime) {
+		this.expirationTime = expirationTime;
+	}
+
+	public Link expirationTime(Date expirationTime) {
+		this.expirationTime = expirationTime;
+		return this;
+	}
+
+	@Override
+	public boolean equals(Object o) {
+		if (this == o)
+			return true;
+		if (o == null || getClass() != o.getClass())
+			return false;
+		if (!super.equals(o))
+			return false;
+		Link link = (Link) o;
+		return rel == link.rel;
+	}
+
+	@Override
+	public int hashCode() {
+		return Objects.hash(super.hashCode(), rel);
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		sb.append("class Link {\n");
+		sb.append("    href: ").append(toIndentedString(getHref())).append("\n");
+		sb.append("    rel: ").append(toIndentedString(rel)).append("\n");
+		sb.append("    type: ").append(toIndentedString(getType())).append("\n");
+		sb.append("    hreflang: ").append(toIndentedString(getHreflang())).append("\n");
+		sb.append("    title: ").append(toIndentedString(getTitle())).append("\n");
+		sb.append("    length: ").append(toIndentedString(getLength())).append("\n");
+		sb.append("}");
+		return sb.toString();
+	}
+
+}
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 0000000000..5783ac23d5
--- /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
+	REQUESTED,
+
+	// Validation started
+	STARTED,
+
+	// Validation failed
+	FAILED,
+
+	// Validation finished
+	FINISHED
+
+}
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/model/StatusNotification.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/model/StatusNotification.java
new file mode 100644
index 0000000000..3ed5fc155b
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/model/StatusNotification.java
@@ -0,0 +1,94 @@
+package de.latlon.xplanbox.api.validator.v2.model;
+
+import static de.latlon.xplanbox.api.validator.v2.model.Link.RelEnum.REPORT;
+import static de.latlon.xplanbox.api.validator.v2.model.StatusEnum.REQUESTED;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Date;
+import java.util.List;
+
+import de.latlon.xplanbox.validator.storage.Status;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+public class StatusNotification {
+
+	private StatusEnum status;
+
+	private String errorMsg;
+
+	private List<Link> links;
+
+	private Date expirationTime;
+
+	public StatusNotification() {
+		this.status = REQUESTED;
+	}
+
+	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;
+	}
+
+	public void setErrorMsg(String errorMsg) {
+		this.errorMsg = errorMsg;
+	}
+
+	public StatusNotification errorMsg(String errorMsg) {
+		this.errorMsg = errorMsg;
+		return this;
+	}
+
+	public List<Link> getLinks() {
+		return links;
+	}
+
+	public void setLinks(List<Link> links) {
+		this.links = links;
+	}
+
+	public StatusNotification links(List<Link> links) {
+		this.links = links;
+		return this;
+	}
+
+	public StatusNotification links(Link... links) {
+		this.links = List.of(links);
+		return this;
+	}
+
+	public static StatusNotification fromStatus(Status status) throws URISyntaxException {
+		StatusNotification statusNotification = new StatusNotification()
+			.status(StatusEnum.valueOf(status.getStatus().name()))
+			.errorMsg(status.getErrorMsg());
+		if (status.getLinkToJsonReport() != null)
+			statusNotification.links(
+					(Link) new Link().rel(REPORT)
+						.expirationTime(status.getExpirationTime())
+						.type("application/json")
+						.title("Validierungsreport")
+						.href(new URI(status.getLinkToJsonReport())),
+					(Link) new Link().rel(REPORT)
+						.expirationTime(status.getExpirationTime())
+						.type("application/pdf")
+						.title("Validierungsreport")
+						.href(new URI(status.getLinkToPdfReport())));
+		return statusNotification;
+	}
+
+}
diff --git a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationMessageReceiver.java b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/model/ValidationReceipt.java
similarity index 57%
rename from xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationMessageReceiver.java
rename to xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/model/ValidationReceipt.java
index 156fd51805..e714f31277 100644
--- a/xplan-core/xplan-core-validator-events/src/main/java/de/latlon/core/validator/events/ValidationMessageReceiver.java
+++ b/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/v2/model/ValidationReceipt.java
@@ -1,6 +1,6 @@
 /*-
  * #%L
- * xplan-core-validator-events - Modul zur Gruppierung der Kernmodule
+ * xplan-core-validator - XPlan Validator Core Komponente
  * %%
  * Copyright (C) 2008 - 2024 Freie und Hansestadt Hamburg, developed by lat/lon gesellschaft für raumbezogene Informationssysteme mbH
  * %%
@@ -8,44 +8,41 @@
  * 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.core.validator.events;
-
-import java.util.function.Consumer;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+package de.latlon.xplanbox.api.validator.v2.model;
 
 /**
+ * A receipt for the submission of a validation request.
+ *
  * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
- * @since 7.2
+ * @since 8.0
  */
-public class ValidationMessageReceiver {
+public class ValidationReceipt {
 
-	private static final Logger LOG = LoggerFactory.getLogger(ValidationMessageReceiver.class);
+	private final String uuid;
 
-	private Consumer<ValidationRequestedEvent> listener;
+	private final Link statusLink;
+
+	public ValidationReceipt(String uuid, Link statusLink) {
+		this.uuid = uuid;
+		this.statusLink = statusLink;
+	}
 
-	void receiveMessage(ValidationRequestedEvent msg) {
-		if (listener != null) {
-			listener.accept(msg);
-		}
-		else {
-			LOG.warn("No listener registered");
-		}
+	public String getUuid() {
+		return uuid;
 	}
 
-	public void setListener(Consumer<ValidationRequestedEvent> listener) {
-		this.listener = listener;
+	public Link getStatusLink() {
+		return statusLink;
 	}
 
 }
diff --git a/xplan-validator/xplan-validator-api/src/main/resources/application-dev.properties b/xplan-validator/xplan-validator-api/src/main/resources/application-dev.properties
new file mode 100644
index 0000000000..7675c93694
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/main/resources/application-dev.properties
@@ -0,0 +1,23 @@
+###
+# #%L
+# xplan-api-validator - Modul zur Gruppierung der REST-API
+# %%
+# 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=8085
\ No newline at end of file
diff --git a/xplan-validator/xplan-validator-api/src/main/resources/application.properties b/xplan-validator/xplan-validator-api/src/main/resources/application.properties
index d22f627251..e7648d4e7c 100644
--- a/xplan-validator/xplan-validator-api/src/main/resources/application.properties
+++ b/xplan-validator/xplan-validator-api/src/main/resources/application.properties
@@ -33,3 +33,16 @@ spring.rabbitmq.port=${XPLAN_RABBIT_PORT:5672}
 spring.rabbitmq.username=${XPLAN_RABBIT_USER:guest}
 
 xplanbox.rabbitmq.internal.prefix=${XPLAN_RABBIT_INTERNAL_PREFIX:xplanbox}
+xplanbox.rabbitmq.fanout.topics=none
+xplanbox.rabbitmq.public.fanout=${XPLAN_RABBIT_PUBLIC_FANOUT:}
+xplanbox.rabbitmq.task.topics=none
+
+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.validation.fsdirectory=${XPLAN_FS_DIRECTORY:/tmp/validation}
+xplanbox.validation.profiles=${XPLAN_VALIDATOR_PROFILES:}
+xplanbox.validation.s3.bucketName=${XPLAN_VALIDATION_S3_BUCKET_NAME:validation}
+xplanbox.validation.s3.bucketPublicUrl=${XPLAN_VALIDATION_S3_BUCKET_PUBLIC_URL}
diff --git a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/config/FakeAsyncValidationWrapper.java b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/config/FakeAsyncValidationWrapper.java
new file mode 100644
index 0000000000..b374418c65
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/config/FakeAsyncValidationWrapper.java
@@ -0,0 +1,51 @@
+package de.latlon.xplanbox.api.validator.config;
+
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import de.latlon.core.validator.events.ValidationRequestedEvent;
+import de.latlon.xplanbox.api.validator.handler.AsyncValidationWrapper;
+import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
+import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage.ReportType;
+
+public class FakeAsyncValidationWrapper extends AsyncValidationWrapper {
+
+	@Autowired
+	private ValidationExecutionStorage validationExecutionStorage;
+
+	private Path reportForNextValidateRequest;
+
+	private ValidationRequestedEvent lastValidatedEvent;
+
+	FakeAsyncValidationWrapper() {
+		super(null);
+	}
+
+	@Override
+	public boolean validate(ValidationRequestedEvent event) {
+		lastValidatedEvent = event;
+
+		try {
+			Map<ReportType, Path> reports = new HashMap<>();
+			reports.put(ReportType.JSON, reportForNextValidateRequest);
+			validationExecutionStorage.saveValidationResult(event.getUuid(), reports);
+		}
+		catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+
+		return true;
+	}
+
+	public void saveReportForNextValidateRequest(boolean successfull, Path validationResult) {
+		reportForNextValidateRequest = validationResult;
+	}
+
+	public ValidationRequestedEvent getLastValidatedEvent() {
+		return lastValidatedEvent;
+	}
+
+}
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 c5e52297cb..b06bb65e2b 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,7 +26,8 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 import static org.slf4j.LoggerFactory.getLogger;
 
-import jakarta.annotation.PostConstruct;
+import java.io.IOException;
+import java.util.Optional;
 
 import org.mockito.Mockito;
 import org.slf4j.Logger;
@@ -35,12 +36,15 @@ import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Primary;
 
-import de.latlon.core.validator.events.ValidationRequestNotifier;
+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;
 
 /**
  * Indented to register the JAX-RS resources within Spring Application Context. TODO
@@ -69,8 +73,18 @@ public class TestContext {
 	}
 
 	@Bean
-	public ValidationRequestNotifier validationRequestNotifier() {
-		return Mockito.mock(ValidationRequestNotifier.class);
+	public EventSender validationRequestNotifier() {
+		return Mockito.mock(EventSender.class);
+	}
+
+	@Bean
+	public FakeAsyncValidationWrapper asyncValidationWrapper() {
+		return new FakeAsyncValidationWrapper();
+	}
+
+	@Bean
+	public ValidationExecutionStorage validationExecutionStorage() throws IOException {
+		return new FileSystemValidationExecutionStorage(Optional.empty());
 	}
 
 	private static SemanticProfileValidator createValidator(RulesMetadata profile) {
diff --git a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/handler/AsyncValidationWrapperTest.java b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/handler/AsyncValidationWrapperTest.java
new file mode 100644
index 0000000000..4833ea1cb0
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/handler/AsyncValidationWrapperTest.java
@@ -0,0 +1,136 @@
+/*-
+ * #%L
+ * xplan-validator-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%
+ */
+package de.latlon.xplanbox.api.validator.handler;
+
+import static de.latlon.core.validator.events.ValidationFinishedEvent.ValidationFinishedStatus.SUCCEEDED;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import de.latlon.core.validator.events.EventSender;
+import de.latlon.core.validator.events.ValidationFinishedEvent;
+import de.latlon.core.validator.events.ValidationRequestedEvent;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+class AsyncValidationWrapperTest {
+
+	private List<String> logs = Collections.synchronizedList(new ArrayList<>());
+
+	@BeforeEach
+	private void cleanup() {
+		logs.clear();
+	}
+
+	@Test
+	void simpleCase() throws Exception {
+		EventSender eventSender = Mockito.mock(EventSender.class);
+		AsyncValidationWrapper wrapper = new AsyncValidationWrapper(eventSender);
+
+		startAsyncValidation(wrapper, someEventWithUuid("uuid1"), "event1");
+		verifyNewLog("event1: before validate");
+
+		// send validation finished event
+		wrapper.someValidationFinished(new ValidationFinishedEvent("uuid1", SUCCEEDED));
+		verifyNewLog("event1: after validate");
+	}
+
+	@Test
+	void moreComplicated() throws Exception {
+		EventSender eventSender = Mockito.mock(EventSender.class);
+		AsyncValidationWrapper wrapper = new AsyncValidationWrapper(eventSender);
+
+		startAsyncValidation(wrapper, someEventWithUuid("uuid1"), "event1");
+		verifyNewLog("event1: before validate");
+
+		startAsyncValidation(wrapper, someEventWithUuid("uuid2"), "event2");
+		verifyNewLog("event2: before validate");
+
+		startAsyncValidation(wrapper, someEventWithUuid("uuid3"), "event3");
+		verifyNewLog("event3: before validate");
+
+		// send validation finished event for something else
+		wrapper.someValidationFinished(new ValidationFinishedEvent("uuidOther", SUCCEEDED));
+
+		// send validation finished event for event 2
+		wrapper.someValidationFinished(new ValidationFinishedEvent("uuid2", SUCCEEDED));
+		verifyNewLog("event2: after validate");
+
+		// send validation finished events for something else
+		wrapper.someValidationFinished(new ValidationFinishedEvent("uuidOther2", SUCCEEDED));
+		wrapper.someValidationFinished(new ValidationFinishedEvent("uuid2", SUCCEEDED));
+
+		// send validation finished event for event 1
+		wrapper.someValidationFinished(new ValidationFinishedEvent("uuid1", SUCCEEDED));
+		verifyNewLog("event1: after validate");
+
+		// send validation finished event for event 1
+		wrapper.someValidationFinished(new ValidationFinishedEvent("uuid3", SUCCEEDED));
+		verifyNewLog("event3: after validate");
+	}
+
+	private void startAsyncValidation(AsyncValidationWrapper wrapper, ValidationRequestedEvent event,
+			String msgPrefix) {
+		new Thread("Thread " + msgPrefix) {
+			public void run() {
+				try {
+					logs.add(msgPrefix + ": before validate");
+					wrapper.validate(event);
+				}
+				catch (Exception e) {
+					logs.add(msgPrefix + ": exception " + e.getMessage());
+				}
+				logs.add(msgPrefix + ": after validate");
+			};
+		}.start();
+	}
+
+	private void verifyNewLog(String expectedNewMessage) throws Exception {
+		waitingIfNeeded(() -> assertThat(logs).containsExactly(expectedNewMessage));
+		logs.clear();
+	}
+
+	private void waitingIfNeeded(Callable<?> callable) throws Exception {
+		long maxWaitTime = System.currentTimeMillis() + 5_000;
+		while (true) {
+			try {
+				callable.call();
+				return;
+			}
+			catch (Throwable t) {
+				if (System.currentTimeMillis() > maxWaitTime) {
+					throw t;
+				}
+				Thread.sleep(1_000);
+			}
+		}
+
+	}
+
+	private ValidationRequestedEvent someEventWithUuid(String uuid) {
+		return new ValidationRequestedEvent(uuid, null, null, null, null);
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/handler/ConfigHandlerTest.java b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/handler/ConfigHandlerTest.java
index 961f69c7d7..d9700cee00 100644
--- a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/handler/ConfigHandlerTest.java
+++ b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/handler/ConfigHandlerTest.java
@@ -33,12 +33,13 @@ import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 
 import de.latlon.xplanbox.api.validator.config.ApplicationContext;
+import de.latlon.xplanbox.api.validator.config.TestContext;
 
 /**
  * @author <a href="mailto:friebe@lat-lon.de">Torsten Friebe</a>
  */
 @ExtendWith(SpringExtension.class)
-@ContextConfiguration(classes = { ApplicationContext.class })
+@ContextConfiguration(classes = { ApplicationContext.class, TestContext.class })
 @ActiveProfiles("test")
 class ConfigHandlerTest {
 
diff --git a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v1/DefaultApiTest.java b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v1/DefaultApiTest.java
index 8b1df4bd5d..7212406d62 100644
--- a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v1/DefaultApiTest.java
+++ b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v1/DefaultApiTest.java
@@ -27,10 +27,14 @@ import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 
+import de.latlon.xplan.commons.configuration.DefaultPropertiesLoader;
+import de.latlon.xplanbox.api.validator.api.v1.ApiV1Config;
+import de.latlon.xplanbox.api.validator.config.ApplicationContext;
+import de.latlon.xplanbox.api.validator.config.TestContext;
+import de.latlon.xplanbox.api.validator.config.ValidatorApiConfiguration;
 import jakarta.servlet.ServletContext;
 import jakarta.ws.rs.core.Application;
 import jakarta.ws.rs.core.Response;
-
 import org.apache.http.HttpHeaders;
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
@@ -42,11 +46,6 @@ import org.mockito.Mockito;
 import org.springframework.boot.test.json.BasicJsonTester;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 
-import de.latlon.xplan.commons.configuration.DefaultPropertiesLoader;
-import de.latlon.xplanbox.api.validator.config.ApplicationContext;
-import de.latlon.xplanbox.api.validator.config.JerseyConfig;
-import de.latlon.xplanbox.api.validator.config.ValidatorApiConfiguration;
-
 /**
  * @author <a href="mailto:friebe@lat-lon.de">Torsten Friebe</a>
  */
@@ -73,12 +72,13 @@ class DefaultApiTest extends JerseyTest {
 		try {
 			ValidatorApiConfiguration validatorConfig = new ValidatorApiConfiguration(
 					new DefaultPropertiesLoader(getClass()));
-			resourceConfig = new JerseyConfig(mockServletContext, validatorConfig);
+			resourceConfig = new ApiV1Config(mockServletContext, validatorConfig);
 		}
 		catch (Exception e) {
 			throw new RuntimeException(e);
 		}
-		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationContext.class);
+		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationContext.class,
+				TestContext.class);
 		resourceConfig.property("contextConfig", context);
 		return resourceConfig;
 	}
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
new file mode 100644
index 0000000000..4af7b8b377
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v1/ValidateApiJerseyTest.java
@@ -0,0 +1,236 @@
+/*-
+ * #%L
+ * xplan-validator-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%
+ */
+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 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;
+import static jakarta.ws.rs.core.MediaType.TEXT_XML;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.apache.http.HttpHeaders;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.io.TempDir;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import de.latlon.core.validator.events.ValidationRequestedEvent.OriginFile;
+import de.latlon.xplan.commons.configuration.DefaultPropertiesLoader;
+import de.latlon.xplan.validator.semantic.profile.SemanticProfiles;
+import de.latlon.xplanbox.api.validator.api.v1.ApiV1Config;
+import de.latlon.xplanbox.api.validator.config.ApplicationContext;
+import de.latlon.xplanbox.api.validator.config.FakeAsyncValidationWrapper;
+import de.latlon.xplanbox.api.validator.config.TestContext;
+import de.latlon.xplanbox.api.validator.config.ValidatorApiConfiguration;
+import jakarta.servlet.ServletContext;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+
+/**
+ * @author <a href="mailto:friebe@lat-lon.de">Torsten Friebe</a>
+ */
+@ExtendWith(SpringExtension.class)
+@ContextConfiguration(classes = { TestContext.class })
+public class ValidateApiJerseyTest extends JerseyTest {
+
+	@TempDir
+	public static Path tempFolder;
+
+	@BeforeAll
+	static void setupFakedWorkspace() throws IOException {
+		Path workspace = tempFolder.resolve("xplan-webservices-validator-wms-memory-workspace");
+		Files.createDirectories(workspace);
+		System.setProperty("DEEGREE_WORKSPACE_ROOT", workspace.getParent().toString());
+	}
+
+	@Autowired
+	private SemanticProfiles semanticProfiles;
+
+	private FakeAsyncValidationWrapper fakeAsyncValidationWrapper;
+
+	@Override
+	protected Application configure() {
+		ResourceConfig resourceConfig;
+		ServletContext mockServletContext = Mockito.mock(ServletContext.class);
+		Mockito.when(mockServletContext.getContextPath()).thenReturn("");
+
+		try {
+			ValidatorApiConfiguration validatorConfig = new ValidatorApiConfiguration(
+					new DefaultPropertiesLoader(getClass()));
+			resourceConfig = new ApiV1Config(mockServletContext, validatorConfig);
+		}
+		catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationContext.class,
+				TestContext.class);
+		fakeAsyncValidationWrapper = context.getBean(FakeAsyncValidationWrapper.class);
+		resourceConfig.property("contextConfig", context);
+		return resourceConfig;
+	}
+
+	@Test
+	void verifyThat_Response_ContainsCorrectStatusCodeAndMediaType() throws IOException, URISyntaxException {
+		final String data = Files.readString(Paths.get(ValidateApiJerseyTest.class.getResource("/xplan.gml").toURI()));
+
+		fakeAsyncValidationWrapper.saveReportForNextValidateRequest(true,
+				Paths.get(getClass().getResource("validation-report1.json").toURI()));
+
+		final Response response = target("/validate").request()
+			.accept(APPLICATION_JSON)
+			.post(Entity.entity(data, TEXT_XML));
+
+		assertThat(fakeAsyncValidationWrapper.getLastValidatedEvent().getOriginFile()).isEqualTo(OriginFile.GML);
+		assertThat(response.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
+		assertThat(response.getHeaderString(HttpHeaders.CONTENT_TYPE)).isEqualTo(APPLICATION_JSON);
+	}
+
+	@Test
+	void verifyThat_validationOctetStream_Response_ContainsXmlEncoding() throws URISyntaxException, IOException {
+		final byte[] data = Files.readAllBytes(Paths.get(getClass().getResource("/bplan_valid_41.zip").toURI()));
+
+		fakeAsyncValidationWrapper.saveReportForNextValidateRequest(true, someJsonReport());
+
+		final Response response = target("/validate").request()
+			.accept(APPLICATION_XML)
+			.post(Entity.entity(data, APPLICATION_OCTET_STREAM));
+
+		assertThat(fakeAsyncValidationWrapper.getLastValidatedEvent().getOriginFile()).isEqualTo(OriginFile.ZIP);
+
+		assertThat(response.getHeaderString(HttpHeaders.CONTENT_TYPE)).isEqualTo(APPLICATION_XML);
+		assertThat(response.readEntity(String.class)).contains("valid");
+	}
+
+	@Test
+	void verifyThat_validationZip_Response_ContainsXmlEncoding() throws Exception {
+		final byte[] data = Files.readAllBytes(Paths.get(getClass().getResource("/bplan_valid_41.zip").toURI()));
+
+		fakeAsyncValidationWrapper.saveReportForNextValidateRequest(true, someJsonReport());
+
+		final Response response = target("/validate").request()
+			.accept(APPLICATION_XML)
+			.post(Entity.entity(data, APPLICATION_ZIP));
+
+		assertThat(fakeAsyncValidationWrapper.getLastValidatedEvent().getOriginFile()).isEqualTo(OriginFile.ZIP);
+
+		assertThat(response.getStatus()).isEqualTo(200);
+		assertThat(response.getHeaderString(HttpHeaders.CONTENT_TYPE)).isEqualTo(APPLICATION_XML);
+		assertThat(response.readEntity(String.class)).contains("valid");
+	}
+
+	@Test
+	void verifyThat_validationXZip_Response_ContainsXmlEncoding() throws Exception {
+		final byte[] data = Files.readAllBytes(Paths.get(getClass().getResource("/bplan_valid_41.zip").toURI()));
+
+		fakeAsyncValidationWrapper.saveReportForNextValidateRequest(true, someJsonReport());
+
+		final Response response = target("/validate").request()
+			.accept(APPLICATION_XML)
+			.post(Entity.entity(data, APPLICATION_X_ZIP));
+
+		assertThat(fakeAsyncValidationWrapper.getLastValidatedEvent().getOriginFile()).isEqualTo(OriginFile.ZIP);
+
+		assertThat(response.getHeaderString(HttpHeaders.CONTENT_TYPE)).isEqualTo(APPLICATION_XML);
+		assertThat(response.readEntity(String.class)).contains("valid");
+	}
+
+	@Test
+	void verifyThat_validationXZipCompressed_Response_ContainsXmlEncoding() throws Exception {
+		final byte[] data = Files.readAllBytes(Paths.get(getClass().getResource("/bplan_valid_41.zip").toURI()));
+
+		fakeAsyncValidationWrapper.saveReportForNextValidateRequest(true, someJsonReport());
+
+		final Response response = target("/validate").request()
+			.accept(APPLICATION_XML)
+			.post(Entity.entity(data, APPLICATION_X_ZIP_COMPRESSED));
+
+		assertThat(fakeAsyncValidationWrapper.getLastValidatedEvent().getOriginFile()).isEqualTo(OriginFile.ZIP);
+
+		assertThat(response.getHeaderString(HttpHeaders.CONTENT_TYPE)).isEqualTo(APPLICATION_XML);
+		assertThat(response.readEntity(String.class)).contains("valid");
+	}
+
+	@Test
+	void verifyThat_validationXZipCompressedWithProfilesCommaseparated_Response_ContainsJsonEncoding()
+			throws Exception {
+
+		fakeAsyncValidationWrapper.saveReportForNextValidateRequest(true, someJsonReport());
+
+		final byte[] data = Files
+			.readAllBytes(Paths.get(ValidateApiJerseyTest.class.getResource("/bplan_valid_41.zip").toURI()));
+		String profileId0 = semanticProfiles.getProfileValidators().get(0).getId();
+		String profileId1 = semanticProfiles.getProfileValidators().get(1).getId();
+		final Response response = target("/validate").queryParam("profiles", profileId0 + "," + profileId1)
+			.request()
+			.accept(APPLICATION_JSON)
+			.post(Entity.entity(data, APPLICATION_X_ZIP_COMPRESSED));
+
+		assertThat(response.getHeaderString(HttpHeaders.CONTENT_TYPE)).isEqualTo(APPLICATION_JSON);
+		assertThat(fakeAsyncValidationWrapper.getLastValidatedEvent().getSettings().getProfiles())
+			.containsExactlyInAnyOrder(profileId0, profileId1);
+	}
+
+	@Test
+	void verifyThat_validationWithInvalidXFileName_Response_IsStatusCode400() throws URISyntaxException, IOException {
+		final byte[] data = Files
+			.readAllBytes(Paths.get(ValidateApiJerseyTest.class.getResource("/bplan_valid_41.zip").toURI()));
+		final Response response = target("/validate").request()
+			.header("X-Filename", "invalid.filename with blanks")
+			.accept(APPLICATION_JSON)
+			.post(Entity.entity(data, APPLICATION_X_ZIP_COMPRESSED));
+
+		assertThat(response.getStatus()).isEqualTo(Response.Status.BAD_REQUEST.getStatusCode());
+	}
+
+	@Test
+	void verifyThat_validationWithInvalidName_Response_IsStatusCode400() throws Exception {
+		final byte[] data = Files
+			.readAllBytes(Paths.get(ValidateApiJerseyTest.class.getResource("/bplan_valid_41.zip").toURI()));
+		final Response response = target("/validate").queryParam("name", "invalid.name with blanks")
+			.request()
+			.accept(APPLICATION_JSON)
+			.post(Entity.entity(data, APPLICATION_X_ZIP_COMPRESSED));
+
+		assertThat(response.getStatus()).isEqualTo(Response.Status.BAD_REQUEST.getStatusCode());
+	}
+
+	Path someJsonReport() throws URISyntaxException {
+		return Paths.get(getClass().getResource("validation-report1.json").toURI());
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v1/ValidateApiTest.java b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v1/ValidateApiTest.java
index 72557f9ab8..39945640cd 100644
--- a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v1/ValidateApiTest.java
+++ b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v1/ValidateApiTest.java
@@ -8,231 +8,82 @@
  * 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.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 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;
-import static jakarta.ws.rs.core.MediaType.TEXT_XML;
 import static org.assertj.core.api.Assertions.assertThat;
 
 import java.io.IOException;
-import java.net.URISyntaxException;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.List;
 
-import jakarta.servlet.ServletContext;
-import jakarta.ws.rs.client.Entity;
-import jakarta.ws.rs.core.Application;
-import jakarta.ws.rs.core.Response;
-
-import org.apache.http.HttpHeaders;
-import org.glassfish.jersey.server.ResourceConfig;
-import org.glassfish.jersey.test.JerseyTest;
-import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
 import org.junit.jupiter.api.io.TempDir;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.AnnotationConfigApplicationContext;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
-
-import de.latlon.xplan.commons.configuration.DefaultPropertiesLoader;
-import de.latlon.xplan.validator.semantic.profile.SemanticProfiles;
-import de.latlon.xplanbox.api.validator.config.ApplicationContext;
-import de.latlon.xplanbox.api.validator.config.JerseyConfig;
-import de.latlon.xplanbox.api.validator.config.TestContext;
-import de.latlon.xplanbox.api.validator.config.ValidatorApiConfiguration;
+
+import de.latlon.core.validator.events.ValidationRequestedEvent;
+import de.latlon.xplanbox.api.validator.handler.AsyncValidationWrapper;
+import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
+import jakarta.ws.rs.core.Request;
 
 /**
- * @author <a href="mailto:friebe@lat-lon.de">Torsten Friebe</a>
  */
-@ExtendWith(SpringExtension.class)
-@ContextConfiguration(classes = { TestContext.class })
-public class ValidateApiTest extends JerseyTest {
+class ValidateApiTest {
 
 	@TempDir
-	public static Path tempFolder;
-
-	@BeforeAll
-	static void setupFakedWorkspace() throws IOException {
-		Path workspace = tempFolder.resolve("xplan-webservices-validator-wms-memory-workspace");
-		Files.createDirectories(workspace);
-		System.setProperty("DEEGREE_WORKSPACE_ROOT", workspace.getParent().toString());
-	}
-
-	@Autowired
-	private SemanticProfiles semanticProfiles;
-
-	@Override
-	protected Application configure() {
-		ResourceConfig resourceConfig;
-		ServletContext mockServletContext = Mockito.mock(ServletContext.class);
-		Mockito.when(mockServletContext.getContextPath()).thenReturn("");
-
-		try {
-			ValidatorApiConfiguration validatorConfig = new ValidatorApiConfiguration(
-					new DefaultPropertiesLoader(getClass()));
-			resourceConfig = new JerseyConfig(mockServletContext, validatorConfig);
-		}
-		catch (Exception e) {
-			throw new RuntimeException(e);
-		}
-		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationContext.class,
-				TestContext.class);
-		resourceConfig.property("contextConfig", context);
-		return resourceConfig;
-	}
+	Path tmpDir;
 
 	@Test
-	void verifyThat_Response_ContainsCorrectStatusCodeAndMediaType() throws IOException, URISyntaxException {
-		final String data = new String(
-				Files.readAllBytes(Paths.get(ValidateApiTest.class.getResource("/xplan.gml").toURI())));
-		final Response response = target("/validate").request()
-			.accept(APPLICATION_JSON)
-			.post(Entity.entity(data, TEXT_XML));
-
-		assertThat(response.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
-		assertThat(response.getHeaderString(HttpHeaders.CONTENT_TYPE)).isEqualTo(APPLICATION_JSON);
-	}
-
-	@Test
-	void verifyThat_validationOctetStream_Response_ContainsXmlEncoding() throws URISyntaxException, IOException {
-		final byte[] data = Files
-			.readAllBytes(Paths.get(ValidateApiTest.class.getResource("/bplan_valid_41.zip").toURI()));
-		final Response response = target("/validate").request()
-			.accept(APPLICATION_XML)
-			.post(Entity.entity(data, APPLICATION_OCTET_STREAM));
-
-		assertThat(response.getHeaderString(HttpHeaders.CONTENT_TYPE)).isEqualTo(APPLICATION_XML);
-		assertThat(response.readEntity(String.class)).contains("valid");
-	}
+	void verifyThatProfilesAreSentToValidator_noProfile() throws Exception {
+		List<String> profilesInEvent = callValidateAndExtractProfilesInValidationRequestEvent(null);
+		assertThat(profilesInEvent).isEmpty();
 
-	@Test
-	void verifyThat_validationZip_Response_ContainsXmlEncoding() throws URISyntaxException, IOException {
-		final byte[] data = Files
-			.readAllBytes(Paths.get(ValidateApiTest.class.getResource("/bplan_valid_41.zip").toURI()));
-		final Response response = target("/validate").request()
-			.accept(APPLICATION_XML)
-			.post(Entity.entity(data, APPLICATION_ZIP));
-
-		assertThat(response.getHeaderString(HttpHeaders.CONTENT_TYPE)).isEqualTo(APPLICATION_XML);
-		assertThat(response.readEntity(String.class)).contains("valid");
-	}
+		profilesInEvent = callValidateAndExtractProfilesInValidationRequestEvent(Collections.emptyList());
+		assertThat(profilesInEvent).isEmpty();
 
-	@Test
-	void verifyThat_validationXZip_Response_ContainsXmlEncoding() throws URISyntaxException, IOException {
-		final byte[] data = Files
-			.readAllBytes(Paths.get(ValidateApiTest.class.getResource("/bplan_valid_41.zip").toURI()));
-		final Response response = target("/validate").request()
-			.accept(APPLICATION_XML)
-			.post(Entity.entity(data, APPLICATION_X_ZIP));
-
-		assertThat(response.getHeaderString(HttpHeaders.CONTENT_TYPE)).isEqualTo(APPLICATION_XML);
-		assertThat(response.readEntity(String.class)).contains("valid");
 	}
 
 	@Test
-	void verifyThat_validationXZipCompressed_Response_ContainsXmlEncoding() throws URISyntaxException, IOException {
-		final byte[] data = Files
-			.readAllBytes(Paths.get(ValidateApiTest.class.getResource("/bplan_valid_41.zip").toURI()));
-		final Response response = target("/validate").request()
-			.accept(APPLICATION_XML)
-			.post(Entity.entity(data, APPLICATION_X_ZIP_COMPRESSED));
-
-		assertThat(response.getHeaderString(HttpHeaders.CONTENT_TYPE)).isEqualTo(APPLICATION_XML);
-		assertThat(response.readEntity(String.class)).contains("valid");
+	void verifyThatProfilesAreSentToValidator_oneProfile() throws Exception {
+		List<String> profilesInEvent = callValidateAndExtractProfilesInValidationRequestEvent(List.of("profile1"));
+		assertThat(profilesInEvent).containsExactlyInAnyOrder("profile1");
 	}
 
 	@Test
-	void verifyThat_validationXZipCompressedWithProfile_Response_ContainsJsonEncoding()
-			throws URISyntaxException, IOException {
-		final byte[] data = Files
-			.readAllBytes(Paths.get(ValidateApiTest.class.getResource("/bplan_valid_41.zip").toURI()));
-		final Response response = target("/validate")
-			.queryParam("profiles", semanticProfiles.getProfileValidators().get(0).getId())
-			.request()
-			.accept(APPLICATION_JSON)
-			.post(Entity.entity(data, APPLICATION_X_ZIP_COMPRESSED));
-
-		assertThat(response.getHeaderString(HttpHeaders.CONTENT_TYPE)).isEqualTo(APPLICATION_JSON);
-		String actual = response.readEntity(String.class);
-		assertThat(actual).contains("profil");
+	void verifyThatProfilesAreSentToValidator_twoProfiles() throws Exception {
+		List<String> profilesInEvent = callValidateAndExtractProfilesInValidationRequestEvent(
+				List.of("profile1", "profile2"));
+		assertThat(profilesInEvent).containsExactlyInAnyOrder("profile1", "profile2");
 	}
 
-	@Test
-	void verifyThat_validationXZipCompressedWithProfiles_Response_ContainsJsonEncoding()
-			throws URISyntaxException, IOException {
-		final byte[] data = Files
-			.readAllBytes(Paths.get(ValidateApiTest.class.getResource("/bplan_valid_41.zip").toURI()));
-		final Response response = target("/validate")
-			.queryParam("profiles", semanticProfiles.getProfileValidators().get(0).getId())
-			.queryParam("profiles", semanticProfiles.getProfileValidators().get(1).getId())
-			.request()
-			.accept(APPLICATION_JSON)
-			.post(Entity.entity(data, APPLICATION_X_ZIP_COMPRESSED));
-
-		assertThat(response.getHeaderString(HttpHeaders.CONTENT_TYPE)).isEqualTo(APPLICATION_JSON);
-		String actual = response.readEntity(String.class);
-		assertThat(actual).contains("profil");
-	}
+	private List<String> callValidateAndExtractProfilesInValidationRequestEvent(List profiles) throws Exception {
+		ValidateApi validateApi = new ValidateApi();
+		validateApi.validationExecutionStorage = Mockito.mock(ValidationExecutionStorage.class);
+		validateApi.validationHandler = Mockito.mock(AsyncValidationWrapper.class);
 
-	@Test
-	void verifyThat_validationXZipCompressedWithProfilesCommaseparated_Response_ContainsJsonEncoding()
-			throws URISyntaxException, IOException {
-		final byte[] data = Files
-			.readAllBytes(Paths.get(ValidateApiTest.class.getResource("/bplan_valid_41.zip").toURI()));
-		final Response response = target("/validate")
-			.queryParam("profiles",
-					semanticProfiles.getProfileValidators().get(0).getId() + ","
-							+ semanticProfiles.getProfileValidators().get(1).getId())
-			.request()
-			.accept(APPLICATION_JSON)
-			.post(Entity.entity(data, APPLICATION_X_ZIP_COMPRESSED));
-
-		assertThat(response.getHeaderString(HttpHeaders.CONTENT_TYPE)).isEqualTo(APPLICATION_JSON);
-		String actual = response.readEntity(String.class);
-		assertThat(actual).contains("profil");
-	}
+		Path tmpFile = tmpDir.resolve("my-file.xml");
+		Files.writeString(tmpFile, "");
+		Request request = Mockito.mock(Request.class);
+		validateApi.validate(request, tmpFile.toFile(), null, null, false, false, false, false, false, profiles);
 
-	@Test
-	void verifyThat_validationWithInvalidXFileName_Response_IsStatusCode400() throws URISyntaxException, IOException {
-		final byte[] data = Files
-			.readAllBytes(Paths.get(ValidateApiTest.class.getResource("/bplan_valid_41.zip").toURI()));
-		final Response response = target("/validate").request()
-			.header("X-Filename", "invalid.filename with blanks")
-			.accept(APPLICATION_JSON)
-			.post(Entity.entity(data, APPLICATION_X_ZIP_COMPRESSED));
-
-		assertThat(response.getStatus()).isEqualTo(Response.Status.BAD_REQUEST.getStatusCode());
-	}
+		ArgumentCaptor<ValidationRequestedEvent> argumentCaptor = ArgumentCaptor
+			.forClass(ValidationRequestedEvent.class);
+		Mockito.verify(validateApi.validationHandler).validate(argumentCaptor.capture());
 
-	@Test
-	void verifyThat_validationWithInvalidName_Response_IsStatusCode400() throws URISyntaxException, IOException {
-		final byte[] data = Files
-			.readAllBytes(Paths.get(ValidateApiTest.class.getResource("/bplan_valid_41.zip").toURI()));
-		final Response response = target("/validate").queryParam("name", "invalid.name with blanks")
-			.request()
-			.accept(APPLICATION_JSON)
-			.post(Entity.entity(data, APPLICATION_X_ZIP_COMPRESSED));
-
-		assertThat(response.getStatus()).isEqualTo(Response.Status.BAD_REQUEST.getStatusCode());
+		ValidationRequestedEvent event = argumentCaptor.getValue();
+		return event.getSettings().getProfiles();
 	}
 
 }
diff --git a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v2/DefaultApi2Test.java b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v2/DefaultApi2Test.java
new file mode 100644
index 0000000000..bdacc0f9d1
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v2/DefaultApi2Test.java
@@ -0,0 +1,139 @@
+/*-
+ * #%L
+ * xplan-validator-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%
+ */
+package de.latlon.xplanbox.api.validator.v2;
+
+import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import de.latlon.xplan.commons.configuration.DefaultPropertiesLoader;
+import de.latlon.xplanbox.api.validator.api.v2.ApiV2Config;
+import de.latlon.xplanbox.api.validator.config.ApplicationContext;
+import de.latlon.xplanbox.api.validator.config.TestContext;
+import de.latlon.xplanbox.api.validator.config.ValidatorApiConfiguration;
+import de.latlon.xplanbox.api.validator.v1.DefaultApi;
+import jakarta.servlet.ServletContext;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import org.apache.http.HttpHeaders;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.mockito.Mockito;
+import org.springframework.boot.test.json.BasicJsonTester;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz</a>
+ * @since 8.0
+ */
+class DefaultApi2Test extends JerseyTest {
+
+	@TempDir
+	static Path tempFolder;
+
+	@BeforeAll
+	static void setupFakedWorkspace() throws IOException {
+		Path workspace = tempFolder.resolve("xplan-webservices-validator-wms-memory-workspace");
+		Files.createDirectories(workspace);
+		System.setProperty("DEEGREE_WORKSPACE_ROOT", workspace.getParent().toString());
+	}
+
+	@Override
+	protected Application configure() {
+		enable(TestProperties.LOG_TRAFFIC);
+
+		ResourceConfig resourceConfig;
+		ServletContext mockServletContext = Mockito.mock(ServletContext.class);
+		Mockito.when(mockServletContext.getContextPath()).thenReturn("");
+
+		try {
+			ValidatorApiConfiguration validatorConfig = new ValidatorApiConfiguration(
+					new DefaultPropertiesLoader(DefaultApi.class));
+			resourceConfig = new ApiV2Config(mockServletContext, validatorConfig);
+		}
+		catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationContext.class,
+				TestContext.class);
+		resourceConfig.property("contextConfig", context);
+		return resourceConfig;
+	}
+
+	@Test
+	void verifyThat_Response_ContainsCorrectStatusCodeAndMediaType() {
+		final Response response = target("/").request(APPLICATION_JSON).get();
+
+		assertThat(response.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
+		assertThat(response.getHeaderString(HttpHeaders.CONTENT_TYPE)).isEqualTo(APPLICATION_JSON);
+	}
+
+	@Test
+	void verifyThat_Response_ContainsOpenApiDocument() {
+		final String response = target("/").request(APPLICATION_JSON).get(String.class);
+
+		BasicJsonTester json = new BasicJsonTester(getClass());
+		assertThat(json.from(response)).extractingJsonPathStringValue("$.openapi").isEqualTo("3.0.1");
+	}
+
+	@Test
+	void verifyThat_Response_ContainsLicence() {
+		final String response = target("/").request(APPLICATION_JSON).get(String.class);
+
+		BasicJsonTester json = new BasicJsonTester(getClass());
+		assertThat(json.from(response)).extractingJsonPathStringValue("$.info.license.name").isEqualTo("Apache 2.0");
+	}
+
+	@Test
+	void verifyThat_Response_Paths() {
+		final String response = target("/").request(APPLICATION_JSON).get(String.class);
+
+		BasicJsonTester json = new BasicJsonTester(getClass());
+		assertThat(json.from(response)).extractingJsonPathMapValue("$.paths")
+			.containsOnlyKeys("/", "/info", "/status/{uuid}", "/validate");
+	}
+
+	@Test
+	void verifyThat_Response_ContainsTermsOfService() {
+		final String response = target("/").request(APPLICATION_JSON).get(String.class);
+
+		BasicJsonTester json = new BasicJsonTester(getClass());
+		assertThat(json.from(response)).extractingJsonPathStringValue("$.info.termsOfService")
+			.isEqualTo("http://xplanbox/api-validator/terms");
+	}
+
+	@Test
+	void verifyThat_Response_ContainsServersUrl() {
+		final String response = target("/").request(APPLICATION_JSON).get(String.class);
+
+		BasicJsonTester json = new BasicJsonTester(getClass());
+		assertThat(json.from(response)).extractingJsonPathStringValue("$.servers[0].url")
+			.isEqualTo("http://xplanbox-api-validator/api/v2");
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v2/InfoApi2Test.java b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v2/InfoApi2Test.java
new file mode 100644
index 0000000000..e3443994b7
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v2/InfoApi2Test.java
@@ -0,0 +1,92 @@
+/*-
+ * #%L
+ * xplan-validator-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%
+ */
+package de.latlon.xplanbox.api.validator.v2;
+
+import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import de.latlon.xplanbox.api.validator.config.ApplicationContext;
+import de.latlon.xplanbox.api.validator.config.TestContext;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import org.apache.http.HttpHeaders;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.springframework.boot.test.json.BasicJsonTester;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz</a>
+ * @since 8.0
+ */
+class InfoApi2Test extends JerseyTest {
+
+	@TempDir
+	public static Path tempFolder;
+
+	@BeforeAll
+	static void setupFakedWorkspace() throws IOException {
+		Path workspace = tempFolder.resolve("xplan-validator-wms-memory-workspace");
+		Files.createDirectories(workspace);
+		System.setProperty("DEEGREE_WORKSPACE_ROOT", workspace.getParent().toString());
+	}
+
+	@Override
+	protected Application configure() {
+		enable(TestProperties.LOG_TRAFFIC);
+		final ResourceConfig resourceConfig = new ResourceConfig(InfoApi2.class);
+		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationContext.class,
+				TestContext.class);
+		resourceConfig.property("contextConfig", context);
+		return resourceConfig;
+	}
+
+	@Test
+	void verifyThat_Response_ContainsCorrectStatusCodeAndMediaType() {
+		final Response response = target("/info").request(APPLICATION_JSON).get();
+
+		assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+		assertEquals(APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
+
+		BasicJsonTester json = new BasicJsonTester(getClass());
+		assertThat(json.from(response.readEntity(String.class))).extractingJsonPathStringValue("$.rulesMetadata.source")
+			.startsWith("https://gitlab.opencode.de/xleitstelle/xplanung/validierungsregeln/standard/-/tree/");
+
+	}
+
+	@Test
+	void verifyThat_Response_ContainsSupportedXplanGmlVersionsAndProfiles() {
+		final String response = target("/info").request(APPLICATION_JSON).get(String.class);
+
+		assertThat(response).contains("supportedXPlanGmlVersions");
+		assertThat(response).contains("profiles");
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v2/StatusApi2Test.java b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v2/StatusApi2Test.java
new file mode 100644
index 0000000000..02f0e28433
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v2/StatusApi2Test.java
@@ -0,0 +1,80 @@
+/*-
+ * #%L
+ * xplan-validator-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%
+ */
+package de.latlon.xplanbox.api.validator.v2;
+
+import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.UUID;
+
+import de.latlon.xplanbox.api.commons.exception.XPlanApiExceptionMapper;
+import de.latlon.xplanbox.api.validator.config.ApplicationContext;
+import de.latlon.xplanbox.api.validator.config.TestContext;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz</a>
+ * @since 8.0
+ */
+class StatusApi2Test extends JerseyTest {
+
+	@TempDir
+	public static Path tempFolder;
+
+	@BeforeAll
+	static void setupFakedWorkspace() throws IOException {
+		Path workspace = tempFolder.resolve("xplan-validator-wms-memory-workspace");
+		Files.createDirectories(workspace);
+		System.setProperty("DEEGREE_WORKSPACE_ROOT", workspace.getParent().toString());
+	}
+
+	@Override
+	protected Application configure() {
+		enable(TestProperties.LOG_TRAFFIC);
+		final ResourceConfig resourceConfig = new ResourceConfig(StatusApi.class);
+		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationContext.class,
+				TestContext.class);
+		resourceConfig.property("contextConfig", context);
+		resourceConfig.register(XPlanApiExceptionMapper.class);
+		return resourceConfig;
+	}
+
+	@Test
+	@Disabled("TODO: fix implementation")
+	void verify_404_forInvalidUuid() {
+		final Response response = target("/status/" + UUID.randomUUID()).request(APPLICATION_JSON).get();
+
+		assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus());
+	}
+
+}
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
new file mode 100644
index 0000000000..c5b4250347
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/v2/ValidateApi2Test.java
@@ -0,0 +1,147 @@
+/*-
+ * #%L
+ * xplan-validator-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%
+ */
+package de.latlon.xplanbox.api.validator.v2;
+
+import static de.latlon.xplanbox.api.commons.XPlanBoxMediaType.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;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import de.latlon.xplan.commons.configuration.DefaultPropertiesLoader;
+import de.latlon.xplan.validator.semantic.profile.SemanticProfiles;
+import de.latlon.xplanbox.api.validator.api.v2.ApiV2Config;
+import de.latlon.xplanbox.api.validator.config.ApplicationContext;
+import de.latlon.xplanbox.api.validator.config.TestContext;
+import de.latlon.xplanbox.api.validator.config.ValidatorApiConfiguration;
+import jakarta.servlet.ServletContext;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import org.apache.http.HttpHeaders;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.io.TempDir;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz</a>
+ * @since 8.0
+ */
+@ExtendWith(SpringExtension.class)
+@ContextConfiguration(classes = { TestContext.class })
+public class ValidateApi2Test extends JerseyTest {
+
+	@TempDir
+	public static Path tempFolder;
+
+	@BeforeAll
+	static void setupFakedWorkspace() throws IOException {
+		Path workspace = tempFolder.resolve("xplan-webservices-validator-wms-memory-workspace");
+		Files.createDirectories(workspace);
+		System.setProperty("DEEGREE_WORKSPACE_ROOT", workspace.getParent().toString());
+	}
+
+	@Autowired
+	private SemanticProfiles semanticProfiles;
+
+	@Override
+	protected Application configure() {
+		ResourceConfig resourceConfig;
+		ServletContext mockServletContext = Mockito.mock(ServletContext.class);
+		Mockito.when(mockServletContext.getContextPath()).thenReturn("");
+
+		try {
+			ValidatorApiConfiguration validatorConfig = new ValidatorApiConfiguration(
+					new DefaultPropertiesLoader(getClass()));
+			resourceConfig = new ApiV2Config(mockServletContext, validatorConfig);
+		}
+		catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationContext.class,
+				TestContext.class);
+		resourceConfig.property("contextConfig", context);
+		return resourceConfig;
+	}
+
+	@Test
+	void verifyThat_Response_ContainsCorrectStatusCodeAndMediaType() throws IOException, URISyntaxException {
+		final String data = new String(
+				Files.readAllBytes(Paths.get(ValidateApi2Test.class.getResource("/xplan.gml").toURI())));
+		final Response response = target("/validate").request()
+			.accept(APPLICATION_JSON)
+			.post(Entity.entity(data, TEXT_XML));
+
+		assertThat(response.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
+		assertThat(response.getHeaderString(HttpHeaders.CONTENT_TYPE)).isEqualTo(APPLICATION_JSON);
+		assertThat(response.readEntity(String.class)).contains("uuid");
+	}
+
+	@Test
+	void verifyThat_validationXZipCompressed_Response_ContainsJsonEncoding() throws URISyntaxException, IOException {
+		final byte[] data = Files
+			.readAllBytes(Paths.get(ValidateApi2Test.class.getResource("/bplan_valid_41.zip").toURI()));
+		final Response response = target("/validate").request()
+			.accept(APPLICATION_JSON)
+			.post(Entity.entity(data, APPLICATION_X_ZIP_COMPRESSED));
+
+		assertThat(response.getHeaderString(HttpHeaders.CONTENT_TYPE)).isEqualTo(APPLICATION_JSON);
+		assertThat(response.readEntity(String.class)).contains("uuid");
+	}
+
+	@Test
+	void verifyThat_validationWithInvalidName_Response_IsStatusCode400() throws URISyntaxException, IOException {
+		final byte[] data = Files.readAllBytes(Paths.get(ValidateApi2Test.class.getResource("/xplan.gml").toURI()));
+		final Response response = target("/validate").queryParam("name", "invalid.name with blanks")
+			.request()
+			.accept(APPLICATION_JSON)
+			.post(Entity.entity(data, TEXT_XML));
+
+		assertThat(response.getStatus()).isEqualTo(Response.Status.BAD_REQUEST.getStatusCode());
+	}
+
+	@Test
+	void verifyThat_validationXZipCompressedWithInvalidName_Response_IsStatusCode400()
+			throws URISyntaxException, IOException {
+		final byte[] data = Files
+			.readAllBytes(Paths.get(ValidateApi2Test.class.getResource("/bplan_valid_41.zip").toURI()));
+		final Response response = target("/validate").queryParam("name", "invalid.name with blanks")
+			.request()
+			.accept(APPLICATION_JSON)
+			.post(Entity.entity(data, APPLICATION_X_ZIP_COMPRESSED));
+
+		assertThat(response.getStatus()).isEqualTo(Response.Status.BAD_REQUEST.getStatusCode());
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-api/src/test/resources/de/latlon/xplanbox/api/validator/v1/validation-report1.json b/xplan-validator/xplan-validator-api/src/test/resources/de/latlon/xplanbox/api/validator/v1/validation-report1.json
new file mode 100644
index 0000000000..3a90816e2e
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/test/resources/de/latlon/xplanbox/api/validator/v1/validation-report1.json
@@ -0,0 +1 @@
+{"documentSummary":[{"name":"Nr. 108 Holstener Weg","type":"BP_Plan"}],"version":"XPLAN_41","filename":null,"name":"8147f2f6-5e53-4fc7-a795-75a6ea4b3190","bbox":{"minX":7.373668092967802,"minY":52.33234200586314,"maxX":7.377600099759094,"maxY":52.33376312995529,"crs":"EPSG:4326"},"date":1721376349423,"valid":false,"status":"Die Validierung wurde ausgeführt.","externalReferences":[],"externalReferencesResult":[],"rulesMetadata":{"version":"unbekannt","source":"unbekannt"},"validationResult":{"semantisch":{"valid":true,"rules":[]},"geometrisch":{"valid":false,"errors":["XPlanAuszug (Zeile 1, Spalte 1): 2.2.2.1: äußerer Ring verwendet falsche Laufrichtung (CW)."],"warnings":[]},"syntaktisch":{"valid":true,"messages":[]}}}
\ No newline at end of file
diff --git a/xplan-validator/xplan-validator-api/src/test/resources/de/latlon/xplanbox/api/validator/v1/validation-report2.xml b/xplan-validator/xplan-validator-api/src/test/resources/de/latlon/xplanbox/api/validator/v1/validation-report2.xml
new file mode 100644
index 0000000000..073a1c07d8
--- /dev/null
+++ b/xplan-validator/xplan-validator-api/src/test/resources/de/latlon/xplanbox/api/validator/v1/validation-report2.xml
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><validationReport><version>XPLAN_41</version><name>858202ca-3d84-4174-be76-be04af280e36</name><documentSummary><name>Nr. 108 Holstener Weg</name><type>BP_Plan</type></documentSummary><bbox><minX>7.373668092967802</minX><minY>52.33234200586314</minY><maxX>7.377600099759094</maxX><maxY>52.33376312995529</maxY><crs>EPSG:4326</crs></bbox><date>2024-07-19T10:26:13.799+02:00</date><valid>false</valid><status>Die Validierung wurde ausgeführt.</status><wmsUrl>https://latlon.xplanbox.develop.diplanung.de/xplan-validator-wms/services/wms?PLANWERK_MANAGERID=4688&amp;SERVICE=WMS&amp;REQUEST=GetCapabilities</wmsUrl><rulesMetadata><version>1.1.9</version><source>https://gitlab.opencode.de/xleitstelle/xplanung/validierungsregeln/standard/-/tree/v1.1.9</source></rulesMetadata><validationResult><geometrisch><valid>false</valid><errors>XPlanAuszug (Zeile 1, Spalte 1): 2.2.2.1: äußerer Ring verwendet falsche Laufrichtung (CW).</errors></geometrisch><semantisch><valid>true</valid><rules><isValid>true</isValid><message>Verwendung vorgegebenen URNs für das uom-Attribut von GML-MeasureType</message><name>2.1.2.1</name></rules><rules><isValid>true</isValid><message>Angabe eines Standard CRS</message><name>2.1.3.1</name></rules><rules><isValid>true</isValid><message>Flächenschlussbedingung</message><name>2.2.1.1</name></rules><rules><isValid>true</isValid><message>Relationen auf Text-Abschnitte</message><name>3.1.1.1</name></rules><rules><isValid>true</isValid><message>Relationen auf Begründungs-Abschnitte</message><name>3.1.1.2</name></rules><rules><isValid>true</isValid><message>Relation auf Präsentationsobjekte</message><name>3.1.2.1</name></rules><rules><isValid>true</isValid><message>Relation auf Fachobjekte</message><name>3.1.2.2</name></rules><rules><isValid>true</isValid><message>Relation auf Basis-Rasterplan</message><name>3.1.2.3</name></rules><rules><isValid>true</isValid><message>Relationen auf Text-Abschnitte</message><name>3.1.3.1</name></rules><rules><isValid>true</isValid><message>Relationen auf Begründungs-Abschnitte</message><name>3.1.3.2</name></rules><rules><isValid>true</isValid><message>Rückwärts-Referenzen auf Plan-Bereiche</message><name>3.1.3.3</name></rules><rules><isValid>true</isValid><message>Rückwärts-Referenzen auf Präsentationsobjekte</message><name>3.1.3.4</name></rules><rules><isValid>true</isValid><message>Spezifikation des Textinhalts</message><name>3.2.1.1</name></rules><rules><isValid>true</isValid><message>Spezifikation des Textinhalts</message><name>3.2.2.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der verschiedenen Höhenangaben</message><name>3.2.3.1</name></rules><rules><isValid>true</isValid><message>Verwendung von Höhenangaben, die sich auf eine auf Bezugshöhe beziehen, die auf Planebene definiert ist</message><name>3.2.3.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute hoehenbezug und abweichenderHoehenbezug</message><name>3.2.3.3</name></rules><rules><isValid>true</isValid><message>Verweis auf Dokumente.</message><name>3.2.4.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute ags (Amtlicher Gemeindeschlüssel) und rs (Regionalschlüssel).</message><name>3.2.5.1</name></rules><rules><isValid>true</isValid><message>Spezifikation des Fachobjekt-Attributs bei nicht-freien Präsentationsobjekten</message><name>3.3.1.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute art und index</message><name>3.3.1.2</name></rules><rules><isValid>true</isValid><message>Rückwärts-Referenzen auf Plan-Bereiche</message><name>3.3.1.3</name></rules><rules><isValid>true</isValid><message>Einschränkung des Raumbezugs auf Punktgeometrie.</message><name>3.3.2.1</name></rules><rules><isValid>true</isValid><message>Einschränkung des Raumbezugs auf Liniengeometrie.</message><name>3.3.3.1</name></rules><rules><isValid>true</isValid><message>Einschränkung des Raumbezugs auf Flächengeometrie.</message><name>3.3.4.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation bereich</message><name>4.1.1.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation inhaltBPlan</message><name>4.1.2.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation rasterAenderung</message><name>4.1.2.2</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation gehoertZuPlan</message><name>4.1.2.3</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation wirdAusgeglichenDurchFlaeche</message><name>4.1.3.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation wirdAusgeglichenDurchMassnahme</message><name>4.1.3.2</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation wirdAusgeglichenDurchSPEMassnahme</message><name>4.1.3.3</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation wirdAusgeglichenDurchSPEFlaeche</message><name>4.1.3.4</name></rules><rules><isValid>true</isValid><message>Rückwärts-Referenzen auf Plan-Bereiche</message><name>4.1.3.5</name></rules><rules><isValid>true</isValid><message>BPlan-Inhalte dürfen nicht gleichzeitig als originärer Planinhalt und nachrichtliche Übernahme in den Plan integriert werden.</message><name>4.1.3.6</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation wirdAusgeglichenDurchABE</message><name>4.1.3.7</name></rules><rules><isValid>true</isValid><message>Nur Flächenobjekte der Basisebene gehören zum Flächenschluss</message><name>4.1.4.1</name></rules><rules><isValid>true</isValid><message>Einschränkung auf Flächengeometrie</message><name>4.1.4.2</name></rules><rules><isValid>true</isValid><message>Nur Flächenobjekte der Basisebene gehören zum Flächenschluss</message><name>4.1.5.1</name></rules><rules><isValid>true</isValid><message>Angabe des Attributs flaechenschluss bei flächenhaftem Raumbezug</message><name>4.1.5.2</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekte gehören nie zum Flächenschluss.</message><name>4.1.6.1</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekte auf Ebene 0 gehören immer zum Flächenschluss</message><name>4.1.7.1</name></rules><rules><isValid>true</isValid><message>Einschränkung auf Liniengeometrie</message><name>4.1.8.1</name></rules><rules><isValid>true</isValid><message>Einschränkung auf Punktgeometrie</message><name>4.1.9.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur GFZ</message><name>4.2.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur GF</message><name>4.2.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur GFZ und GF</message><name>4.2.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur BMZ</message><name>4.2.4</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur BM</message><name>4.2.5</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur BMZ und BM</message><name>4.2.6</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur GRZ</message><name>4.2.7</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur GR</message><name>4.2.8</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur GRZ und GR</message><name>4.2.9</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zu Z</message><name>4.2.10</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zu ZU</message><name>4.2.11</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur Dachneigung</message><name>4.3.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute dachform und detaillierteDachform</message><name>4.3.2</name></rules><rules><isValid>true</isValid><message>Relation abweichungText</message><name>4.5.1.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute allgArtDerBaulNutzung und besondereArtDerBaulNutzung</message><name>4.5.1.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute besondereArtDerBaulNutzung und sondernutzung</message><name>4.5.1.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute bauweise und abweichendeBauweise</message><name>4.5.1.4</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute detaillierteArtDer BaulNutzung, allgArtDerBaulNutzung, besondereArtDerBaulNutzung und sondernutzung</message><name>4.5.1.5</name></rules><rules><isValid>true</isValid><message>Relation baugrenze</message><name>4.5.2.1</name></rules><rules><isValid>true</isValid><message>Relation baulinie</message><name>4.5.2.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute typ und sonstTyp</message><name>4.5.10.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.5.13.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>4.5.13.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>4.5.13.3</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.5.14.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>4.5.14.2</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation eigentümer</message><name>4.5.14.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>4.5.14.4</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>4.5.15.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>4.6.3.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.7.1.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen</message><name>4.7.1.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>4.7.1.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung</message><name>4.7.1.4</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi (i = 1, 2, 3, 4)</message><name>4.7.1.5</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung</message><name>4.7.1.6</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.7.2.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>4.7.2.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>4.7.2.3</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.8.1.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>4.8.1.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>4.8.1.3</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.8.2.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>4.8.2.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>4.8.2.3</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekt bei flächenhaftem Raumbezug</message><name>4.8.2.4</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.8.3.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen</message><name>4.8.3.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>4.8.3.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung</message><name>4.8.3.4</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi</message><name>4.8.3.5</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung</message><name>4.8.3.6</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute massnahme und weitereMassnahme1</message><name>4.9.2.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereMassnahme2und weitereMassnahme1</message><name>4.9.2.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen</message><name>4.9.2.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute massnahme und weitereMassnahme1</message><name>4.9.3.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereMassnahme2und weitereMassnahme1</message><name>4.9.3.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen</message><name>4.9.3.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute massnahme und weitereMassnahme1</message><name>4.9.5.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereMassnahme2und weitereMassnahme1</message><name>4.9.5.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen</message><name>4.9.5.3</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>4.9.5.4</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>4.9.6.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>4.10.2.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.11.1.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen</message><name>4.11.1.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>4.11.1.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung</message><name>4.11.1.4</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi</message><name>4.11.1.5</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung</message><name>4.11.1.6</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekt bei flächenhaftem Raumbezug</message><name>4.11.1.7</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation begrenzungslinie</message><name>4.12.1.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation begrenzungslinie</message><name>4.12.2.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>4.12.2.2</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>4.12.3.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung</message><name>4.13.1.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung</message><name>4.13.2.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.14.1.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>4.14.2.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute startWinkel und endWinkel</message><name>4.14.3.1</name></rules><rules><isValid>true</isValid><message>Kein flächenhafter Raumbezug</message><name>4.14.3.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.14.4.1</name></rules><rules><isValid>true</isValid><message>Notwendige Spezifikation einer Textlichen Darstellung</message><name>4.14.6.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Relation hoehenangabe</message><name>4.14.7.1</name></rules><rules><isValid>true</isValid><message>Kein flächenhafter Raumbezug</message><name>4.14.7.2</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation bereich</message><name>5.1.1.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute planArt und sonstPlanArt</message><name>5.1.1.2</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation inhaltFPlan</message><name>5.1.2.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation rasterAenderung</message><name>5.1.2.2</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation gehoertZuPlan</message><name>5.1.2.3</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation wirdAusgeglichenDurchFlaeche</message><name>5.1.3.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation wirdAusgeglichenDurchSPE</message><name>5.1.3.2</name></rules><rules><isValid>true</isValid><message>Rückwärts-Referenzen auf Plan-Bereiche</message><name>5.1.3.3</name></rules><rules><isValid>true</isValid><message>FPlan-Inhalte dürfen nicht gleichzeitig als originärer Planinhalt und nachrichtliche Übernahme in den Plan integriert werden.</message><name>5.1.3.4</name></rules><rules><isValid>true</isValid><message>Nur Flächenobjekte der Basisebene gehören zum Flächenschluss</message><name>5.1.4.1</name></rules><rules><isValid>true</isValid><message>Einschränkung auf Flächengeometrie</message><name>5.1.4.2</name></rules><rules><isValid>true</isValid><message>Nur Flächenobjekte der Basisebene gehören zum Flächenschluss</message><name>5.1.5.1</name></rules><rules><isValid>true</isValid><message>Angabe des Attributs flaechenschluss bei flächenhaftem Raumbezug</message><name>5.1.5.2</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekte gehören nie zum Flächenschluss</message><name>5.1.6.1</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekte der Ebene 0 gehören zum Flächenschluss</message><name>5.1.7.1</name></rules><rules><isValid>true</isValid><message>Einschränkung auf Liniengeometrie</message><name>5.1.8.1</name></rules><rules><isValid>true</isValid><message>Einschränkung auf Punktgeometrie</message><name>5.1.9.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute allgArtDerBaulNutzung und besondereArtDerBaulNutzung</message><name>5.3.1.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute besondereArtDerBaulNutzung und sonderNutzung</message><name>5.3.1.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute detaillierteArtDer BaulNutzung, allgArtDerBaulNutzung, besondereArtDerBaulNutzung und sonderNutzung</message><name>5.3.1.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur GFZ</message><name>5.3.1.4</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>5.4.1.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen</message><name>5.4.1.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>5.4.1.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung</message><name>5.4.1.4</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi (i = 1, 2, 3, 4, 5)</message><name>5.4.1.5</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung</message><name>5.4.1.6</name></rules><rules><isValid>true</isValid><message>Einschränkung des Raumbezugs</message><name>5.4.1.7</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekt bei flächenhaftem Raumbezug</message><name>5.4.1.8</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>5.4.2.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation einer einzigen detaillierter Zweckbestimmung</message><name>5.4.2.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>5.4.2.3</name></rules><rules><isValid>true</isValid><message>Einschränkung des Raumbezugs</message><name>5.4.2.4</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekt bei flächenhaftem Raumbezug</message><name>5.4.2.5</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>5.5.1.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>5.5.1.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>5.5.1.3</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>5.5.2.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>5.5.2.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>5.5.2.3</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>5.5.3.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen</message><name>5.5.3.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>5.5.3.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung</message><name>5.5.3.4</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi (i = 1, 2, 3, 4, 5)</message><name>5.5.3.5</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung</message><name>5.5.3.6</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekt bei flächenhaftem Raumbezug</message><name>5.5.3.7</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute massnahme, weitereMassnahme1 und weitereMassnahme2</message><name>5.6.1.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen</message><name>5.6.1.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute massnahme, weitereMassnahme1 und weitereMassnahme2</message><name>5.6.2.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen</message><name>5.6.2.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>5.7.1.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen</message><name>5.7.1.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>5.7.1.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung</message><name>5.7.1.4</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereZweckbestimmungi und weitereBesondZweckbestimmungi (i = 1, 2, 3)</message><name>5.7.1.5</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung</message><name>5.7.1.6</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekt bei flächenhaftem Raumbezug</message><name>5.7.1.7</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung</message><name>5.8.1.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung</message><name>5.8.1.2</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>5.8.1.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>5.9.1.1</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekt bei flächenhaftem Raumbezug</message><name>5.9.1.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>5.9.2.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>5.9.2.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>5.10.1.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>5.10.2.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen</message><name>5.10.2.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung</message><name>5.10.2.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereZweckbestimmungi und weitereBesondZweckbestimmungi (i = 1, 2)</message><name>5.10.2.4</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>5.10.3.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>5.10.4.1</name></rules><rules><isValid>true</isValid><message>Notwendige Spezifikation einer Textlichen Darstellung</message><name>5.10.6.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation bereich</message><name>6.1.1.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation inhaltSoPlan</message><name>6.1.2.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation rasterAenderung</message><name>6.1.2.2</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation gehoertZuPlan</message><name>6.1.2.3</name></rules><rules><isValid>true</isValid><message>Rückwärts-Referenzen auf Plan-Bereiche</message><name>6.1.3.1</name></rules><rules><isValid>true</isValid><message>SOPlan-Inhalte dürfen nicht gleichzeitig als originärer Planinhalt und nachrichtliche Übernahme in den Plan integriert werden.</message><name>6.1.3.2</name></rules><rules><isValid>true</isValid><message>Nur Flächenobjekte der Basisebene gehören zum Flächenschluss</message><name>6.1.4.1</name></rules><rules><isValid>true</isValid><message>Einschränkung auf Flächengeometrie</message><name>6.1.4.2</name></rules><rules><isValid>true</isValid><message>Nur Flächenobjekte der Basisebene gehören zum Flächenschluss</message><name>6.1.5.1</name></rules><rules><isValid>true</isValid><message>Angabe des Attributs flaechenschluss bei flächenhaftem Raumbezug</message><name>6.1.5.2</name></rules><rules><isValid>true</isValid><message>Einschränkung auf Liniengeometrie</message><name>6.1.6.1</name></rules><rules><isValid>true</isValid><message>Einschränkung auf Punktgeometrie</message><name>6.1.7.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.2.1.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>6.2.1.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.2.2.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>6.2.2.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.2.3.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.2.4.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und besondereArtDerFestlegung</message><name>6.2.5.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung, besondereArtDerFestlegung und detailArtDerFestlegung</message><name>6.2.5.2</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekt bei flächenhaftem Raumbezug</message><name>6.2.5.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.2.6.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.2.7.1</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekt bei flächenhaftem Raumbezug</message><name>6.2.7.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.2.8.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.3.1.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>6.3.1.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.3.2.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>6.3.2.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.3.3.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>6.3.3.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute gebietsArt und sonstGebietsArt</message><name>6.4.1.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>6.4.1.2</name></rules><rules><isValid>true</isValid><message>Konsistenz von typ und sonstTyp</message><name>6.5.1.1</name></rules></semantisch><syntaktisch><valid>true</valid></syntaktisch></validationResult></validationReport>
\ No newline at end of file
diff --git a/xplan-validator/xplan-validator-executor/Dockerfile b/xplan-validator/xplan-validator-executor/Dockerfile
new file mode 100644
index 0000000000..8d209e5130
--- /dev/null
+++ b/xplan-validator/xplan-validator-executor/Dockerfile
@@ -0,0 +1,44 @@
+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 JAR_FILE=target/*.jar
+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_JAVA17_EXPORTS="--add-exports=java.desktop/com.sun.imageio.spi=ALL-UNNAMED" \
+    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 DEEGREE_WORKSPACE_ROOT=/xplanbox/deegree \
+    JAVA_ADDITIONAL_ARG_APP="-Djavax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl -Djts.overlay=ng -Duser.timezone=Europe/Berlin" \
+    XPLANBOX_CONFIG="/xplanbox/xplan-validator-config/"
+
+COPY ${JAR_FILE} /xplanbox/app.jar
+COPY run.sh /xplanbox/
+
+USER 1001
+
+ENTRYPOINT ["/bin/sh", "/xplanbox/run.sh"]
diff --git a/xplan-validator/xplan-validator-executor/README.md b/xplan-validator/xplan-validator-executor/README.md
new file mode 100644
index 0000000000..98c9a27570
--- /dev/null
+++ b/xplan-validator/xplan-validator-executor/README.md
@@ -0,0 +1,11 @@
+# xPlanValidatorExecutor
+
+## Development
+
+The application can be started locally with
+
+```
+mvn spring-boot:run -Dspring-boot.run.profiles=dev
+```
+
+(RabbitMQ required on localhost:5672 with credentials guest/guest)
diff --git a/xplan-validator/xplan-validator-executor/pom.xml b/xplan-validator/xplan-validator-executor/pom.xml
new file mode 100644
index 0000000000..666341e8a3
--- /dev/null
+++ b/xplan-validator/xplan-validator-executor/pom.xml
@@ -0,0 +1,217 @@
+<?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/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>xplan-validator-executor</artifactId>
+
+  <parent>
+    <groupId>de.latlon.product.xplanbox</groupId>
+    <artifactId>xplan-validator</artifactId>
+    <version>8.0-SNAPSHOT</version>
+  </parent>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+        <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>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <!-- xPlanBox -->
+    <dependency>
+      <groupId>de.latlon.product.xplanbox</groupId>
+      <artifactId>xplan-core-validator-events</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>de.latlon.product.xplanbox</groupId>
+      <artifactId>xplan-validator-storage</artifactId>
+    </dependency>
+    <!-- XPlanung -->
+    <dependency>
+      <groupId>de.xleitstelle.xplanung</groupId>
+      <artifactId>regeln</artifactId>
+    </dependency>
+    <!-- spring -->
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-web</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>org.apache.tomcat.embed</groupId>
+          <artifactId>tomcat-embed-el</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.slf4j</groupId>
+          <artifactId>jul-to-slf4j</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.slf4j</groupId>
+          <artifactId>log4j-over-slf4j</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.apache.logging.log4j</groupId>
+          <artifactId>log4j-to-slf4j</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>ch.qos.logback</groupId>
+          <artifactId>logback-classic</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>ch.qos.logback</groupId>
+          <artifactId>logback-core</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.yaml</groupId>
+          <artifactId>snakeyaml</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-amqp</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>org.apache.logging.log4j</groupId>
+          <artifactId>log4j-to-slf4j</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>ch.qos.logback</groupId>
+          <artifactId>logback-classic</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>ch.qos.logback</groupId>
+          <artifactId>logback-core</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.yaml</groupId>
+          <artifactId>snakeyaml</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-actuator</artifactId>
+    </dependency>
+    <!-- logging -->
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>jcl-over-slf4j</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>jul-to-slf4j</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-slf4j2-impl</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-layout-template-json</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>de.latlon.product.xplanbox</groupId>
+      <artifactId>xplan-core-validator</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>de.latlon.product.xplanbox</groupId>
+      <artifactId>xplan-core-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>jakarta.inject</groupId>
+      <artifactId>jakarta.inject-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.dataformat</groupId>
+      <artifactId>jackson-dataformat-xml</artifactId>
+    </dependency>
+        <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.assertj</groupId>
+      <artifactId>assertj-core</artifactId>
+      <scope>test</scope>
+    </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>75</docker-contextTarFile.expectedSizeInMat10pct>
+      </properties>
+      <dependencies>
+        <dependency> <!-- to copy jmx exporter stuff from docker image  -->
+          <groupId>de.latlon.product.xplanbox</groupId>
+          <artifactId>xplan-docker-tomcat</artifactId>
+          <version>${project.version}</version>
+          <type>pom</type>
+        </dependency>
+        <!-- Profiles -->
+        <dependency>
+          <groupId>de.xleitstelle.xplanung</groupId>
+          <artifactId>regeln-berlin</artifactId>
+        </dependency>
+        <dependency>
+          <groupId>de.xleitstelle.xplanung</groupId>
+          <artifactId>regeln-brandenburg</artifactId>
+        </dependency>
+      </dependencies>
+    </profile>
+  </profiles>
+
+</project>
\ No newline at end of file
diff --git a/xplan-validator/xplan-validator-executor/run.sh b/xplan-validator/xplan-validator-executor/run.sh
new file mode 100755
index 0000000000..d12d67ccd8
--- /dev/null
+++ b/xplan-validator/xplan-validator-executor/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.jar
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
new file mode 100644
index 0000000000..3e676f94fc
--- /dev/null
+++ b/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/PlanValidator.java
@@ -0,0 +1,155 @@
+package de.latlon.xplanbox.validator.executor;
+
+import static de.latlon.xplanbox.validator.storage.ErrorType.INTERNAL_ERROR;
+import static de.latlon.xplanbox.validator.storage.ErrorType.INVALID_REQUEST;
+import static de.latlon.xplanbox.validator.storage.ErrorType.fromStatusCode;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+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.xplan.commons.archive.XPlanArchive;
+import de.latlon.xplan.validator.ValidatorException;
+import de.latlon.xplan.validator.report.ValidatorReport;
+import de.latlon.xplanbox.api.commons.ObjectMapperContextResolver;
+import de.latlon.xplanbox.api.commons.ValidationReportBuilder;
+import de.latlon.xplanbox.api.commons.exception.XPlanApiException;
+import de.latlon.xplanbox.api.commons.v1.model.ValidationReport;
+import de.latlon.xplanbox.validator.executor.handler.ValidationHandler;
+import de.latlon.xplanbox.validator.storage.StatusType;
+import de.latlon.xplanbox.validator.storage.StoredValidationReport;
+import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
+import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage.ReportType;
+
+/**
+ * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
+ * @since 8.0
+ */
+@Component
+public class PlanValidator {
+
+	private static final Logger LOG = LoggerFactory.getLogger(PlanValidator.class);
+
+	private final ValidationExecutionStorage validationExecutionStorage;
+
+	private final ValidationHandler validationHandler;
+
+	private final EventSender eventSender;
+
+	public PlanValidator(ValidationExecutionStorage validationExecutionStorage, ValidationHandler validationHandler,
+			EventSender eventSender) {
+		this.validationExecutionStorage = validationExecutionStorage;
+		this.validationHandler = validationHandler;
+		this.eventSender = eventSender;
+	}
+
+	public void validate(ValidationRequestedEvent event) throws Exception {
+		validationExecutionStorage.changeStatus(event.getUuid(), StatusType.STARTED);
+		eventSender.sendPublicEvent(
+				new XPlanboxPublicV1Event(EventType.VALIDATION_START, event.getUuid(), "validation started"));
+
+		try {
+			doValidate(event);
+		}
+		finally {
+			eventSender.sendPublicEvent(
+					new XPlanboxPublicV1Event(EventType.VALIDATION_FINISHED, event.getUuid(), "validation finished"));
+		}
+	}
+
+	private void doValidate(ValidationRequestedEvent event) throws Exception {
+		Map<ReportType, Path> reports = new HashMap<>();
+		try {
+			validationExecutionStorage.changeStatus(event.getUuid(), StatusType.STARTED);
+			Path tmpPath = Files.createTempFile(event.getUuid(), ".rcv");
+			if (Files.exists(tmpPath))
+				Files.delete(tmpPath);
+			validationExecutionStorage.writePlanToValidate(event.getUuid(), tmpPath);
+
+			final XPlanArchive archive;
+			if (event.getOriginFile() == ValidationRequestedEvent.OriginFile.GML) {
+				archive = validationHandler.createArchiveFromGml(tmpPath.toFile(),
+						event.getSettings().getValidationName());
+			}
+			else {
+				archive = validationHandler.createArchiveFromZip(tmpPath.toFile(),
+						event.getSettings().getValidationName());
+			}
+
+			LOG.info("Validating {}", tmpPath);
+			ValidatorReport validatorReport = validationHandler.validate(archive, event.getxFileName(),
+					event.getSettings());
+			// TODO: delete tmpPath
+
+			ValidationReport validationReport = createValidationReport(event, archive, validatorReport);
+
+			reports.put(ReportType.JSON, createJsonReportFile(validationReport));
+			reports.put(ReportType.PDF, createPdfReportFile(validatorReport));
+			reports.put(ReportType.ZIP, createZipReportFile(validatorReport));
+
+			StoredValidationReport storedValidationReport = validationExecutionStorage
+				.saveValidationResult(event.getUuid(), reports);
+			LOG.info("Validation Report: " + validatorReport);
+			validationExecutionStorage.changeStatus(event.getUuid(), StatusType.FINISHED, storedValidationReport);
+			validationExecutionStorage.cleanupAfterValidation(event.getUuid());
+		}
+		catch (XPlanApiException e) {
+			validationExecutionStorage.changeStatus(event.getUuid(), e.getMessage(), fromStatusCode(e.getStatusCode()));
+			LOG.info("Validation with uuid " + event.getUuid() + " failed: " + e.getMessage());
+			throw e;
+		}
+		catch (ValidatorException e) {
+			validationExecutionStorage.changeStatus(event.getUuid(), e.getMessage(), INVALID_REQUEST);
+			LOG.info("Validation with uuid " + event.getUuid() + " failed: " + e.getMessage());
+			throw e;
+		}
+		catch (Exception e) {
+			validationExecutionStorage.changeStatus(event.getUuid(), e.getMessage(), INTERNAL_ERROR);
+			LOG.info("Validation with uuid " + event.getUuid() + " failed: " + e.getMessage());
+			throw e;
+		}
+		finally {
+			for (Path path : reports.values()) {
+				Files.deleteIfExists(path);
+			}
+		}
+	}
+
+	private ValidationReport createValidationReport(ValidationRequestedEvent event, final XPlanArchive archive,
+			ValidatorReport validatorReport) {
+		URI wmsUrl = validationHandler.addToWms(archive);
+		return new ValidationReportBuilder().validatorReport(validatorReport) //
+			.filename(event.getxFileName()) //
+			.wmsUrl(wmsUrl) //
+			.build();
+	}
+
+	private Path createJsonReportFile(ValidationReport validationReport) throws IOException {
+		ObjectMapper mapper = new ObjectMapperContextResolver().getContext(ValidationReport.class);
+		Path reportFile = Files.createTempFile("", ".json");
+		mapper.writeValue(reportFile.toFile(), validationReport);
+		return reportFile;
+	}
+
+	private Path createPdfReportFile(ValidatorReport validatorReport) throws IOException {
+		return validationHandler.writePdfReport(validatorReport);
+	}
+
+	private Path createZipReportFile(ValidatorReport validatorReport) throws IOException {
+		return validationHandler.zipReports(validatorReport);
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/SpringBootApp.java b/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/SpringBootApp.java
new file mode 100644
index 0000000000..57497839cd
--- /dev/null
+++ b/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/SpringBootApp.java
@@ -0,0 +1,54 @@
+/*-
+ * #%L
+ * xplan-validator-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%
+ */
+package de.latlon.xplanbox.validator.executor;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+import org.springframework.context.annotation.ComponentScan;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+@SpringBootApplication
+@ComponentScan(basePackages = { "de.latlon.xplanbox.validator.executor" })
+@EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class })
+public class SpringBootApp extends SpringBootServletInitializer {
+
+	public static void main(String[] args) {
+		SpringApplication.run(SpringBootApp.class, args);
+	}
+
+	/**
+	 * Runs the application as deployable WAR.
+	 * @param application Spring application builder
+	 * @return Spring application builder with this application configured
+	 */
+	@Override
+	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+		return application.sources(SpringBootApp.class);
+	}
+
+}
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
new file mode 100644
index 0000000000..c223b5d3e5
--- /dev/null
+++ b/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/config/ApplicationContext.java
@@ -0,0 +1,162 @@
+/*-
+ * #%L
+ * xplan-validator-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%
+ */
+package de.latlon.xplanbox.validator.executor.config;
+
+import static java.nio.file.Files.createTempDirectory;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+import de.latlon.xplan.commons.configuration.PropertiesLoader;
+import de.latlon.xplan.commons.configuration.SystemPropertyPropertiesLoader;
+import de.latlon.xplan.manager.web.shared.ConfigurationException;
+import de.latlon.xplan.validator.XPlanValidator;
+import de.latlon.xplan.validator.configuration.ValidatorConfiguration;
+import de.latlon.xplan.validator.configuration.ValidatorConfigurationParser;
+import de.latlon.xplan.validator.geometric.GeometricValidator;
+import de.latlon.xplan.validator.geometric.GeometricValidatorImpl;
+import de.latlon.xplan.validator.report.ReportArchiveGenerator;
+import de.latlon.xplan.validator.report.ReportWriter;
+import de.latlon.xplan.validator.semantic.SemanticValidator;
+import de.latlon.xplan.validator.semantic.configuration.SemanticRulesConfiguration;
+import de.latlon.xplan.validator.semantic.configuration.SemanticRulesMainConfiguration;
+import de.latlon.xplan.validator.semantic.configuration.xquery.XQuerySemanticValidatorConfigurationRetriever;
+import de.latlon.xplan.validator.semantic.profile.SemanticProfiles;
+import de.latlon.xplan.validator.semantic.profile.SemanticProfilesCreator;
+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.validator.storage.ValidationExecutionStorage;
+import de.latlon.xplanbox.validator.storage.config.AmazonS3Context;
+import de.latlon.xplanbox.validator.storage.filesystem.FileSystemValidationExecutionStorage;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.Profile;
+import org.springframework.core.io.ResourceLoader;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+@Configuration
+@Import({ ValidatorWmsContext.class, AmazonS3Context.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");
+	}
+
+	@Bean
+	public SyntacticValidator syntacticValidator() {
+		return new SyntacticValidatorImpl();
+	}
+
+	@Bean
+	public GeometricValidator geometricValidator() {
+		return new GeometricValidatorImpl();
+	}
+
+	@Bean
+	public SemanticValidator semanticValidator(XQuerySemanticValidatorConfigurationRetriever configurationRetriever)
+			throws ConfigurationException {
+		return new XQuerySemanticValidator(configurationRetriever);
+	}
+
+	@Bean
+	public XQuerySemanticValidatorConfigurationRetriever xQuerySemanticValidatorConfigurationRetriever(
+			SemanticRulesConfiguration semanticRulesConfiguration) {
+		return new XQuerySemanticValidatorConfigurationRetriever(semanticRulesConfiguration);
+	}
+
+	@Bean
+	public SemanticRulesConfiguration semanticRulesConfiguration(ValidatorConfiguration validatorConfiguration) {
+		Path validationRulesDirectory = validatorConfiguration.getValidationRulesDirectory();
+		return new SemanticRulesMainConfiguration(validationRulesDirectory);
+	}
+
+	@Bean
+	public SemanticProfiles semanticProfiles(ValidatorConfiguration validatorConfiguration,
+			PropertiesLoader validatorPropertiesLoader,
+			@Value("${xplanbox.validation.profiles}") String activatedProfiles) throws ConfigurationException {
+		List<String> activatedProfilesList = activatedProfiles != null ? Arrays.asList(activatedProfiles.split(","))
+				: Collections.emptyList();
+		SemanticProfilesCreator semanticProfilesCreator = new SemanticProfilesCreator(validatorConfiguration,
+				validatorPropertiesLoader, resourceLoader);
+		return semanticProfilesCreator.createSemanticProfiles(activatedProfilesList);
+	}
+
+	@Bean
+	public PropertiesLoader validatorPropertiesLoader() {
+		return new SystemPropertyPropertiesLoader(ValidatorConfiguration.class);
+	}
+
+	@Bean
+	public ValidatorConfiguration validatorConfiguration(PropertiesLoader validatorPropertiesLoader)
+			throws IOException, ConfigurationException {
+		ValidatorConfigurationParser validatorConfigurationParser = new ValidatorConfigurationParser();
+		return validatorConfigurationParser.parse(validatorPropertiesLoader);
+	}
+
+	@Bean
+	public XPlanValidator xplanValidator(GeometricValidator geometricValidator, SyntacticValidator syntacticValidator,
+			SemanticValidator semanticValidator, SemanticProfiles semanticProfiles,
+			ReportArchiveGenerator reportArchiveGenerator) {
+		return new XPlanValidator(geometricValidator, syntacticValidator, semanticValidator,
+				semanticProfiles.getProfileValidators(), reportArchiveGenerator);
+	}
+
+	@Bean
+	public ReportArchiveGenerator reportArchiveGenerator(ValidatorConfiguration validatorConfiguration) {
+		return new ReportArchiveGenerator(validatorConfiguration);
+	}
+
+	@Bean
+	public ReportWriter reportWriter() {
+		return new ReportWriter();
+	}
+
+	@Bean
+	@Profile("!s3execution")
+	public ValidationExecutionStorage validationExecutionStorage(
+			@Value("${xplanbox.validation.fsdirectory}") Optional<Path> fsExecutionDir) throws IOException {
+		return new FileSystemValidationExecutionStorage(fsExecutionDir);
+	}
+
+}
diff --git a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/messagingrabbitmq/Receiver.java b/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/config/ExecutorRabbitConfiguration.java
similarity index 56%
rename from xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/messagingrabbitmq/Receiver.java
rename to xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/config/ExecutorRabbitConfiguration.java
index 11f147b3f1..6741c53ed1 100644
--- a/xplan-manager/xplan-manager-api/src/main/java/de/latlon/xplanbox/api/manager/messagingrabbitmq/Receiver.java
+++ b/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/config/ExecutorRabbitConfiguration.java
@@ -18,30 +18,15 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  * #L%
  */
-package de.latlon.xplanbox.api.manager.messagingrabbitmq;
+package de.latlon.xplanbox.validator.executor.config;
 
-import static org.slf4j.LoggerFactory.getLogger;
+import de.latlon.core.validator.events.RabbitEmitterConfig;
+import de.latlon.core.validator.events.RabbitReceiverConfig;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
 
-import java.util.function.Consumer;
-
-import org.slf4j.Logger;
-import org.springframework.stereotype.Component;
-
-import de.latlon.core.validator.events.ValidationMessageReceiver;
-import de.latlon.core.validator.events.ValidationRequestedEvent;
-
-@Component
-public class Receiver implements Consumer<ValidationRequestedEvent> {
-
-	private static final Logger LOG = getLogger(Receiver.class);
-
-	Receiver(ValidationMessageReceiver msgReceiver) {
-		msgReceiver.setListener(this);
-	}
-
-	@Override
-	public void accept(ValidationRequestedEvent e) {
-		LOG.info("Received event: " + e);
-	}
+@Configuration
+@Import({ RabbitReceiverConfig.class, RabbitEmitterConfig.class })
+public class ExecutorRabbitConfiguration {
 
 }
diff --git a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/handler/ValidationHandler.java b/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/handler/ValidationHandler.java
similarity index 99%
rename from xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/handler/ValidationHandler.java
rename to xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/handler/ValidationHandler.java
index 2d01d0a471..f7b49c38b9 100644
--- a/xplan-validator/xplan-validator-api/src/main/java/de/latlon/xplanbox/api/validator/handler/ValidationHandler.java
+++ b/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/handler/ValidationHandler.java
@@ -18,7 +18,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  * #L%
  */
-package de.latlon.xplanbox.api.validator.handler;
+package de.latlon.xplanbox.validator.executor.handler;
 
 import de.latlon.xplan.commons.archive.XPlanArchive;
 import de.latlon.xplan.commons.archive.XPlanArchiveCreator;
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
new file mode 100644
index 0000000000..f1f00e2588
--- /dev/null
+++ b/xplan-validator/xplan-validator-executor/src/main/java/de/latlon/xplanbox/validator/executor/messagingrabbitmq/Receiver.java
@@ -0,0 +1,71 @@
+/*-
+ * #%L
+ * xplan-manager-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%
+ */
+package de.latlon.xplanbox.validator.executor.messagingrabbitmq;
+
+import static de.latlon.core.validator.events.ValidationFinishedEvent.ValidationFinishedStatus.FAILED;
+import static de.latlon.core.validator.events.ValidationFinishedEvent.ValidationFinishedStatus.SUCCEEDED;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import de.latlon.core.validator.events.EventSender;
+import de.latlon.core.validator.events.ValidationFinishedEvent;
+import de.latlon.core.validator.events.ValidationRequestedEvent;
+import de.latlon.xplanbox.validator.executor.PlanValidator;
+import org.slf4j.Logger;
+import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
+ * @since 8.0
+ */
+@Component
+@RabbitListener(queues = "#{validationTaskQueue.name}", concurrency = "1")
+public class Receiver {
+
+	private static final Logger LOG = getLogger(Receiver.class);
+
+	@Autowired
+	private PlanValidator validator;
+
+	@Autowired
+	private EventSender eventSender;
+
+	@RabbitHandler
+	public void accept(ValidationRequestedEvent event) {
+		LOG.info("Received event: " + event);
+
+		try {
+			validator.validate(event);
+
+			ValidationFinishedEvent finishedEvent = new ValidationFinishedEvent(event.getUuid(), SUCCEEDED);
+			eventSender.sendEvent(finishedEvent);
+		}
+		catch (Exception e) {
+			LOG.error("Failed to process event. Discarding it", e);
+
+			ValidationFinishedEvent finishedEvent = new ValidationFinishedEvent(event.getUuid(), FAILED);
+			eventSender.sendEvent(finishedEvent);
+		}
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-executor/src/main/resources/application-dev.properties b/xplan-validator/xplan-validator-executor/src/main/resources/application-dev.properties
new file mode 100644
index 0000000000..526d01eb7e
--- /dev/null
+++ b/xplan-validator/xplan-validator-executor/src/main/resources/application-dev.properties
@@ -0,0 +1,23 @@
+###
+# #%L
+# xplan-api-validator-executor - Modul zur Gruppierung der REST-API
+# %%
+# 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=8094
\ No newline at end of file
diff --git a/xplan-validator/xplan-validator-executor/src/main/resources/application.properties b/xplan-validator/xplan-validator-executor/src/main/resources/application.properties
new file mode 100644
index 0000000000..61cd9f4955
--- /dev/null
+++ b/xplan-validator/xplan-validator-executor/src/main/resources/application.properties
@@ -0,0 +1,50 @@
+###
+# #%L
+# xplan-api-validator - Modul zur Gruppierung der REST-API
+# %%
+# 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%
+###
+server.servlet.context-path=/xplan-validator-executor
+
+logging.level.root=warn
+logging.level.de.latlon=debug
+logging.level.org.springframework.web=debug
+logging.level.org.hibernate=error
+
+management.endpoint.health.probes.enabled=true
+
+spring.rabbitmq.host=${XPLAN_RABBIT_HOST:localhost}
+spring.rabbitmq.password=${XPLAN_RABBIT_PASSWORD:guest}
+spring.rabbitmq.port=${XPLAN_RABBIT_PORT:5672}
+spring.rabbitmq.username=${XPLAN_RABBIT_USER:guest}
+spring.rabbitmq.listener.prefetch=1
+
+xplanbox.rabbitmq.internal.prefix=${XPLAN_RABBIT_INTERNAL_PREFIX:xplanbox}
+xplanbox.rabbitmq.public.fanout=${XPLAN_RABBIT_PUBLIC_FANOUT:}
+
+xplanbox.rabbitmq.fanout.topics=none
+xplanbox.rabbitmq.task.topics=task.#
+
+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.validation.fsdirectory=${XPLAN_FS_DIRECTORY:/tmp/validation}
+xplanbox.validation.profiles=${XPLAN_VALIDATOR_PROFILES:}
+xplanbox.validation.s3.bucketName=${XPLAN_VALIDATION_S3_BUCKET_NAME:validation}
+xplanbox.validation.s3.bucketPublicUrl=${XPLAN_VALIDATION_S3_BUCKET_PUBLIC_URL}
diff --git a/xplan-validator/xplan-validator-executor/src/main/resources/log4j2.yaml b/xplan-validator/xplan-validator-executor/src/main/resources/log4j2.yaml
new file mode 100644
index 0000000000..fa1df7f8bf
--- /dev/null
+++ b/xplan-validator/xplan-validator-executor/src/main/resources/log4j2.yaml
@@ -0,0 +1,82 @@
+###
+# #%L
+# xplan-validator-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: XPlanValidatorExecutor
+  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:de/latlon/xplan/commons/minimalist-format.json
+
+  Loggers:
+    Root:
+      level: info
+      AppenderRef:
+        - ref: ${appenderToUse}
+          level: info
+    Logger:
+      - name: org.deegree
+        level: info
+      - name: de.latlon.xplan
+        level: info
+      - name: de.latlon.xplanbox.api
+        level: info
+      - name: de.latlon.xplanbox.api.validator.config
+        level: info
+      - name: org.springframework
+        level: warn
+      - name: org.glassfish
+        level: warn
+      - name: org.glassfish.jersey
+        level: warn
+      - name: org.apache
+        level: warn
+      - name: net.sf.jasperreports
+        level: warn
+      - name: com.ctc.wstx
+        level: warn
+      - name: com.sun.xml
+        level: warn
+      - name: org.reflections
+        level: fatal
+      - name: io.swagger.v3
+        level: warn
+      - name: org.deegree.geometry.standard.AbstractDefaultGeometry
+        level: fatal
+      - name: de.latlon.xplan.validator.geometric.XPlanGeometryInspector
+        level: fatal
+      - name: de.latlon.xplan.validator.semantic.configuration.xquery.XQuerySemanticValidatorConfigurationRetriever
+        level: warn 
+      - name: bind
+        level: error
+      - name: logger
+        level: error
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
new file mode 100644
index 0000000000..45a735d2aa
--- /dev/null
+++ b/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/PlanValidatorTest.java
@@ -0,0 +1,196 @@
+/*-
+ * #%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.validator.executor;
+
+import static de.latlon.xplan.validator.web.shared.ValidationType.GEOMETRIC;
+import static de.latlon.xplan.validator.web.shared.ValidationType.SEMANTIC;
+import static de.latlon.xplan.validator.web.shared.ValidationType.SYNTACTIC;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+
+import org.json.JSONObject;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.TestConfiguration;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Primary;
+
+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.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.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.xplan.validator.web.shared.ValidationSettings;
+import de.latlon.xplan.validator.web.shared.ValidationType;
+import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
+import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage.ReportType;
+
+/**
+ * @author <a href="mailto:guillemot@lat-lon.de">Marc Guillemot</a>
+ * @since 8.0
+ */
+@SpringBootTest(classes = { SpringBootApp.class })
+class PlanValidatorTest {
+
+	@TestConfiguration
+	static class TestConfig {
+
+		@Primary
+		@Bean
+		public SemanticProfiles fakeSemanticProfiles() {
+			RulesMetadata profile1 = new RulesMetadata("id1", "test1", "description1", "0.1", "unbekannt");
+			RulesMetadata profile2 = new RulesMetadata("id2", "test2", "description2", "0.2", "lokal");
+			return new SemanticProfiles().add(profile1, createValidator(profile1))
+				.add(profile2, createValidator(profile2));
+		}
+
+		private static SemanticProfileValidator createValidator(RulesMetadata profile) {
+			SemanticProfileValidator semanticProfileValidator = mock(SemanticProfileValidator.class);
+			when(semanticProfileValidator.getId()).thenReturn(profile.getId());
+			SemanticValidatorResult result = mock(SemanticValidatorResult.class);
+			when(result.getRulesMetadata()).thenReturn(profile);
+			when(semanticProfileValidator.validateSemantic(any(SemanticValidableXPlanArchive.class), anyList()))
+				.thenReturn(result);
+			return semanticProfileValidator;
+		}
+
+	}
+
+	@MockBean
+	EventSender eventSender;
+
+	@Captor
+	ArgumentCaptor<XPlanboxPublicV1Event> publicEventCaptor;
+
+	@Autowired
+	PlanValidator validator;
+
+	@Autowired
+	ValidationExecutionStorage validationExecutionStorage;
+
+	@Autowired
+	ObjectMapper jsonMapper;
+
+	@Autowired
+	private SemanticProfiles semanticProfiles;
+
+	@Test
+	// from old
+	// ValidateApiTest.verifyThat_Response_ContainsCorrectStatusCodeAndMediaType
+	void validateGmlJsonReport() throws Exception {
+
+		Path pathToPlan = Paths.get(getClass().getResource("/xplan.gml").toURI());
+		String uuid = validationExecutionStorage.addPlanToValidate(pathToPlan);
+
+		List<ValidationType> validationTypes = List.of(SYNTACTIC, SEMANTIC, GEOMETRIC);
+		ValidationSettings settings = new ValidationSettings("edfd613e-b85d-4ea6-9b97-bb33712b1ba6", validationTypes,
+				null);
+		ValidationRequestedEvent event = new ValidationRequestedEvent(uuid, settings,
+				null /* filename */, MediaType.JSON, OriginFile.GML);
+
+		validator.validate(event);
+
+		verifyExpectedReport(uuid, ReportType.JSON, "report1.expected.json");
+
+		XPlanboxPublicV1Event expectedStartEvent = new XPlanboxPublicV1Event(EventType.VALIDATION_START, uuid,
+				"validation started");
+		XPlanboxPublicV1Event expectedFinishedEvent = new XPlanboxPublicV1Event(EventType.VALIDATION_FINISHED, uuid,
+				"validation finished");
+		Mockito.verify(eventSender, times(2)).sendPublicEvent(publicEventCaptor.capture());
+		assertThat(publicEventCaptor.getAllValues()).containsExactly(expectedStartEvent, expectedFinishedEvent);
+	}
+
+	@Test
+	// from old
+	// ValidateApiTest.verifyThat_validationXZipCompressedWithProfile_Response_ContainsJsonEncoding()
+	void valideZipWithOneProfile() throws Exception {
+		Path pathToPlan = Paths.get(getClass().getResource("/bplan_valid_41.zip").toURI());
+		String uuid = validationExecutionStorage.addPlanToValidate(pathToPlan);
+
+		List<ValidationType> validationTypes = List.of(SYNTACTIC, SEMANTIC, GEOMETRIC);
+		List<String> profiles = List.of(semanticProfiles.getProfileValidators().get(0).getId());
+		ValidationSettings settings = new ValidationSettings("8dc3163c-a361-49b8-9c53-3733f7d61274", validationTypes,
+				profiles, null /* extendedOptions */);
+		ValidationRequestedEvent event = new ValidationRequestedEvent(uuid, settings, null, MediaType.JSON,
+				OriginFile.ZIP);
+
+		validator.validate(event);
+
+		verifyExpectedReport(uuid, ReportType.JSON, "report6.expected.json");
+	}
+
+	@Test
+	// from old
+	// ValidateApiTest.verifyThat_validationXZipCompressedWithProfiles_Response_ContainsJsonEncoding()
+	void valideZipWithTwoProfiles() throws Exception {
+		Path pathToPlan = Paths.get(getClass().getResource("/bplan_valid_41.zip").toURI());
+		String uuid = validationExecutionStorage.addPlanToValidate(pathToPlan);
+
+		List<ValidationType> validationTypes = List.of(SYNTACTIC, SEMANTIC, GEOMETRIC);
+		List<String> profiles = List.of(semanticProfiles.getProfileValidators().get(0).getId());
+		ValidationSettings settings = new ValidationSettings("6463c72f-4a7d-40d0-a129-3de95fdd0eb8", validationTypes,
+				profiles, null /* extendedOptions */);
+		ValidationRequestedEvent event = new ValidationRequestedEvent(uuid, settings, null, MediaType.JSON,
+				OriginFile.ZIP);
+
+		validator.validate(event);
+
+		verifyExpectedReport(uuid, ReportType.JSON, "report7.expected.json");
+	}
+
+	private void verifyExpectedReport(String uuid, ReportType reportType, String expectedReportFile) throws Exception {
+		String jsonReport = new String(validationExecutionStorage.retrieveReport(uuid, reportType),
+				StandardCharsets.UTF_8);
+
+		String expectedReport = Files.readString(Paths.get(getClass().getResource(expectedReportFile).toURI()));
+		assertThat(sanitizeDates(jsonReport)).isEqualTo(sanitizeDates(expectedReport));
+	}
+
+	private String sanitizeDates(String s) throws Exception {
+		s = s.replaceAll("\"date\":\"[^\"]+\"", "\"date\":\"-fixed-for-comparison-\"");
+		JSONObject json = new JSONObject(s);
+		return json.toString(4);
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/handler/ValidationHandlerTest.java b/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/handler/ValidationHandlerTest.java
similarity index 91%
rename from xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/handler/ValidationHandlerTest.java
rename to xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/handler/ValidationHandlerTest.java
index 3132d2cc73..5287428ec0 100644
--- a/xplan-validator/xplan-validator-api/src/test/java/de/latlon/xplanbox/api/validator/handler/ValidationHandlerTest.java
+++ b/xplan-validator/xplan-validator-executor/src/test/java/de/latlon/xplanbox/validator/executor/handler/ValidationHandlerTest.java
@@ -18,7 +18,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  * #L%
  */
-package de.latlon.xplanbox.api.validator.handler;
+package de.latlon.xplanbox.validator.executor.handler;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -36,32 +36,31 @@ import java.net.URISyntaxException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.junit.jupiter.api.io.TempDir;
-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.junit.jupiter.SpringExtension;
-
+import de.latlon.core.validator.events.EventSender;
 import de.latlon.xplan.commons.archive.XPlanArchive;
 import de.latlon.xplan.validator.ValidatorException;
 import de.latlon.xplan.validator.report.ValidatorReport;
 import de.latlon.xplan.validator.web.shared.ValidationSettings;
 import de.latlon.xplanbox.api.commons.exception.InvalidXPlanGmlOrArchive;
-import de.latlon.xplanbox.api.validator.config.ApplicationContext;
+import de.latlon.xplanbox.validator.executor.SpringBootApp;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
 
 /**
  * @author <a href="mailto:friebe@lat-lon.de">Torsten Friebe</a>
  * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
  */
-@ExtendWith(SpringExtension.class)
-@ContextConfiguration(classes = { ApplicationContext.class })
-@ActiveProfiles("test")
+@SpringBootTest(classes = { SpringBootApp.class })
 public class ValidationHandlerTest {
 
+	@MockBean
+	EventSender eventSender;
+
 	@TempDir
 	public static Path tempFolder;
 
diff --git a/xplan-validator/xplan-validator-executor/src/test/resources/bplan_valid_41.zip b/xplan-validator/xplan-validator-executor/src/test/resources/bplan_valid_41.zip
new file mode 100644
index 0000000000000000000000000000000000000000..3b382162672e420c133b227c2c5b8c6ebad7d6aa
GIT binary patch
literal 1652
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

literal 0
HcmV?d00001

diff --git a/xplan-validator/xplan-validator-executor/src/test/resources/config/application.properties b/xplan-validator/xplan-validator-executor/src/test/resources/config/application.properties
new file mode 100644
index 0000000000..bf0a025176
--- /dev/null
+++ b/xplan-validator/xplan-validator-executor/src/test/resources/config/application.properties
@@ -0,0 +1,26 @@
+###
+# #%L
+# xplan-api-validator - Modul zur Gruppierung der REST-API
+# %%
+# 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%
+###
+
+# properties overwritten for unit/integration tests
+
+spring.profiles.active=test
+
+spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration
\ No newline at end of file
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
new file mode 100644
index 0000000000..98e35f8add
--- /dev/null
+++ b/xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report1.expected.json
@@ -0,0 +1,1697 @@
+{
+    "date": "-fixed-for-comparison-",
+    "valid": false,
+    "externalReferences": [],
+    "externalReferencesResult": [],
+    "rulesMetadata": {
+        "source": "https:\/\/gitlab.opencode.de\/xleitstelle\/xplanung\/validierungsregeln\/standard\/-\/tree\/v1.1.9",
+        "version": "1.1.9"
+    },
+    "filename": null,
+    "validationResult": {
+        "syntaktisch": {
+            "valid": true,
+            "messages": []
+        },
+        "semantisch": {
+            "valid": true,
+            "rules": [
+                {
+                    "isValid": true,
+                    "name": "2.1.2.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung vorgegebenen URNs für das uom-Attribut von GML-MeasureType",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "2.1.3.1",
+                    "warnedFeatures": [],
+                    "message": "Angabe eines Standard CRS",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "2.2.1.1",
+                    "warnedFeatures": [],
+                    "message": "Flächenschlussbedingung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.1.1.1",
+                    "warnedFeatures": [],
+                    "message": "Relationen auf Text-Abschnitte",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.1.1.2",
+                    "warnedFeatures": [],
+                    "message": "Relationen auf Begründungs-Abschnitte",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.1.2.1",
+                    "warnedFeatures": [],
+                    "message": "Relation auf Präsentationsobjekte",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.1.2.2",
+                    "warnedFeatures": [],
+                    "message": "Relation auf Fachobjekte",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.1.2.3",
+                    "warnedFeatures": [],
+                    "message": "Relation auf Basis-Rasterplan",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.1.3.1",
+                    "warnedFeatures": [],
+                    "message": "Relationen auf Text-Abschnitte",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.1.3.2",
+                    "warnedFeatures": [],
+                    "message": "Relationen auf Begründungs-Abschnitte",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.1.3.3",
+                    "warnedFeatures": [],
+                    "message": "Rückwärts-Referenzen auf Plan-Bereiche",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.1.3.4",
+                    "warnedFeatures": [],
+                    "message": "Rückwärts-Referenzen auf Präsentationsobjekte",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.2.1.1",
+                    "warnedFeatures": [],
+                    "message": "Spezifikation des Textinhalts",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.2.2.1",
+                    "warnedFeatures": [],
+                    "message": "Spezifikation des Textinhalts",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.2.3.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der verschiedenen Höhenangaben",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.2.3.2",
+                    "warnedFeatures": [],
+                    "message": "Verwendung von Höhenangaben, die sich auf eine auf Bezugshöhe beziehen, die auf Planebene definiert ist",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.2.3.3",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute hoehenbezug und abweichenderHoehenbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.2.4.1",
+                    "warnedFeatures": [],
+                    "message": "Verweis auf Dokumente.",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.2.5.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute ags (Amtlicher Gemeindeschlüssel) und rs (Regionalschlüssel).",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.3.1.1",
+                    "warnedFeatures": [],
+                    "message": "Spezifikation des Fachobjekt-Attributs bei nicht-freien Präsentationsobjekten",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.3.1.2",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute art und index",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.3.1.3",
+                    "warnedFeatures": [],
+                    "message": "Rückwärts-Referenzen auf Plan-Bereiche",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.3.2.1",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung des Raumbezugs auf Punktgeometrie.",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.3.3.1",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung des Raumbezugs auf Liniengeometrie.",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "3.3.4.1",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung des Raumbezugs auf Flächengeometrie.",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.1.1.1",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation bereich",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.1.2.1",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation inhaltBPlan",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.1.2.2",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation rasterAenderung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.1.2.3",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation gehoertZuPlan",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.1.3.1",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation wirdAusgeglichenDurchFlaeche",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.1.3.2",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation wirdAusgeglichenDurchMassnahme",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.1.3.3",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation wirdAusgeglichenDurchSPEMassnahme",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.1.3.4",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation wirdAusgeglichenDurchSPEFlaeche",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.1.3.5",
+                    "warnedFeatures": [],
+                    "message": "Rückwärts-Referenzen auf Plan-Bereiche",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.1.3.6",
+                    "warnedFeatures": [],
+                    "message": "BPlan-Inhalte dürfen nicht gleichzeitig als originärer Planinhalt und nachrichtliche Übernahme in den Plan integriert werden.",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.1.3.7",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation wirdAusgeglichenDurchABE",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.1.4.1",
+                    "warnedFeatures": [],
+                    "message": "Nur Flächenobjekte der Basisebene gehören zum Flächenschluss",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.1.4.2",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung auf Flächengeometrie",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.1.5.1",
+                    "warnedFeatures": [],
+                    "message": "Nur Flächenobjekte der Basisebene gehören zum Flächenschluss",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.1.5.2",
+                    "warnedFeatures": [],
+                    "message": "Angabe des Attributs flaechenschluss bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.1.6.1",
+                    "warnedFeatures": [],
+                    "message": "Überlagerungsobjekte gehören nie zum Flächenschluss.",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.1.7.1",
+                    "warnedFeatures": [],
+                    "message": "Flächenschlussobjekte auf Ebene 0 gehören immer zum Flächenschluss",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.1.8.1",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung auf Liniengeometrie",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.1.9.1",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung auf Punktgeometrie",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.2.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Angaben zur GFZ",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.2.2",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Angaben zur GF",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.2.3",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Angaben zur GFZ und GF",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.2.4",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Angaben zur BMZ",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.2.5",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Angaben zur BM",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.2.6",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Angaben zur BMZ und BM",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.2.7",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Angaben zur GRZ",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.2.8",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Angaben zur GR",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.2.9",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Angaben zur GRZ und GR",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.2.10",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Angaben zu Z",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.2.11",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Angaben zu ZU",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.3.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Angaben zur Dachneigung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.3.2",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute dachform und detaillierteDachform",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.5.1.1",
+                    "warnedFeatures": [],
+                    "message": "Relation abweichungText",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.5.1.2",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute allgArtDerBaulNutzung und besondereArtDerBaulNutzung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.5.1.3",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute besondereArtDerBaulNutzung und sondernutzung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.5.1.4",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute bauweise und abweichendeBauweise",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.5.1.5",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute detaillierteArtDer BaulNutzung, allgArtDerBaulNutzung, besondereArtDerBaulNutzung und sondernutzung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.5.2.1",
+                    "warnedFeatures": [],
+                    "message": "Relation baugrenze",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.5.2.2",
+                    "warnedFeatures": [],
+                    "message": "Relation baulinie",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.5.10.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute typ und sonstTyp",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.5.13.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.5.13.2",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.5.13.3",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.5.14.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.5.14.2",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.5.14.3",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation eigentümer",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.5.14.4",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.5.15.1",
+                    "warnedFeatures": [],
+                    "message": "Überlagerungsobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.6.3.1",
+                    "warnedFeatures": [],
+                    "message": "Überlagerungsobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.7.1.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.7.1.2",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.7.1.3",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.7.1.4",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.7.1.5",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi (i = 1, 2, 3, 4)",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.7.1.6",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.7.2.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.7.2.2",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.7.2.3",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.8.1.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.8.1.2",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.8.1.3",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.8.2.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.8.2.2",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.8.2.3",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.8.2.4",
+                    "warnedFeatures": [],
+                    "message": "Flächenschlussobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.8.3.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.8.3.2",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.8.3.3",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.8.3.4",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.8.3.5",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.8.3.6",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.9.2.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute massnahme und weitereMassnahme1",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.9.2.2",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute weitereMassnahme2und weitereMassnahme1",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.9.2.3",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.9.3.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute massnahme und weitereMassnahme1",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.9.3.2",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute weitereMassnahme2und weitereMassnahme1",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.9.3.3",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.9.5.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute massnahme und weitereMassnahme1",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.9.5.2",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute weitereMassnahme2und weitereMassnahme1",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.9.5.3",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.9.5.4",
+                    "warnedFeatures": [],
+                    "message": "Überlagerungsobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.9.6.1",
+                    "warnedFeatures": [],
+                    "message": "Überlagerungsobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.10.2.1",
+                    "warnedFeatures": [],
+                    "message": "Überlagerungsobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.11.1.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.11.1.2",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.11.1.3",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.11.1.4",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.11.1.5",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.11.1.6",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.11.1.7",
+                    "warnedFeatures": [],
+                    "message": "Flächenschlussobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.12.1.1",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation begrenzungslinie",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.12.2.1",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation begrenzungslinie",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.12.2.2",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.12.3.1",
+                    "warnedFeatures": [],
+                    "message": "Überlagerungsobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.13.1.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.13.2.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.14.1.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.14.2.1",
+                    "warnedFeatures": [],
+                    "message": "Überlagerungsobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.14.3.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute startWinkel und endWinkel",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.14.3.2",
+                    "warnedFeatures": [],
+                    "message": "Kein flächenhafter Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.14.4.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.14.6.1",
+                    "warnedFeatures": [],
+                    "message": "Notwendige Spezifikation einer Textlichen Darstellung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.14.7.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Relation hoehenangabe",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "4.14.7.2",
+                    "warnedFeatures": [],
+                    "message": "Kein flächenhafter Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.1.1.1",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation bereich",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.1.1.2",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute planArt und sonstPlanArt",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.1.2.1",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation inhaltFPlan",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.1.2.2",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation rasterAenderung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.1.2.3",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation gehoertZuPlan",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.1.3.1",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation wirdAusgeglichenDurchFlaeche",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.1.3.2",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation wirdAusgeglichenDurchSPE",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.1.3.3",
+                    "warnedFeatures": [],
+                    "message": "Rückwärts-Referenzen auf Plan-Bereiche",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.1.3.4",
+                    "warnedFeatures": [],
+                    "message": "FPlan-Inhalte dürfen nicht gleichzeitig als originärer Planinhalt und nachrichtliche Übernahme in den Plan integriert werden.",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.1.4.1",
+                    "warnedFeatures": [],
+                    "message": "Nur Flächenobjekte der Basisebene gehören zum Flächenschluss",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.1.4.2",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung auf Flächengeometrie",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.1.5.1",
+                    "warnedFeatures": [],
+                    "message": "Nur Flächenobjekte der Basisebene gehören zum Flächenschluss",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.1.5.2",
+                    "warnedFeatures": [],
+                    "message": "Angabe des Attributs flaechenschluss bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.1.6.1",
+                    "warnedFeatures": [],
+                    "message": "Überlagerungsobjekte gehören nie zum Flächenschluss",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.1.7.1",
+                    "warnedFeatures": [],
+                    "message": "Flächenschlussobjekte der Ebene 0 gehören zum Flächenschluss",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.1.8.1",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung auf Liniengeometrie",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.1.9.1",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung auf Punktgeometrie",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.3.1.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute allgArtDerBaulNutzung und besondereArtDerBaulNutzung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.3.1.2",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute besondereArtDerBaulNutzung und sonderNutzung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.3.1.3",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute detaillierteArtDer BaulNutzung, allgArtDerBaulNutzung, besondereArtDerBaulNutzung und sonderNutzung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.3.1.4",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Angaben zur GFZ",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.4.1.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.4.1.2",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.4.1.3",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.4.1.4",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.4.1.5",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi (i = 1, 2, 3, 4, 5)",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.4.1.6",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.4.1.7",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung des Raumbezugs",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.4.1.8",
+                    "warnedFeatures": [],
+                    "message": "Flächenschlussobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.4.2.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.4.2.2",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation einer einzigen detaillierter Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.4.2.3",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.4.2.4",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung des Raumbezugs",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.4.2.5",
+                    "warnedFeatures": [],
+                    "message": "Flächenschlussobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.5.1.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.5.1.2",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.5.1.3",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.5.2.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.5.2.2",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.5.2.3",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.5.3.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.5.3.2",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.5.3.3",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.5.3.4",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.5.3.5",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi (i = 1, 2, 3, 4, 5)",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.5.3.6",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.5.3.7",
+                    "warnedFeatures": [],
+                    "message": "Flächenschlussobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.6.1.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute massnahme, weitereMassnahme1 und weitereMassnahme2",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.6.1.2",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.6.2.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute massnahme, weitereMassnahme1 und weitereMassnahme2",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.6.2.2",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.7.1.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.7.1.2",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.7.1.3",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.7.1.4",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.7.1.5",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute weitereZweckbestimmungi und weitereBesondZweckbestimmungi (i = 1, 2, 3)",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.7.1.6",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.7.1.7",
+                    "warnedFeatures": [],
+                    "message": "Flächenschlussobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.8.1.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.8.1.2",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.8.1.3",
+                    "warnedFeatures": [],
+                    "message": "Überlagerungsobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.9.1.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.9.1.2",
+                    "warnedFeatures": [],
+                    "message": "Flächenschlussobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.9.2.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.9.2.2",
+                    "warnedFeatures": [],
+                    "message": "Überlagerungsobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.10.1.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.10.2.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.10.2.2",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.10.2.3",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.10.2.4",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute weitereZweckbestimmungi und weitereBesondZweckbestimmungi (i = 1, 2)",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.10.3.1",
+                    "warnedFeatures": [],
+                    "message": "Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.10.4.1",
+                    "warnedFeatures": [],
+                    "message": "Überlagerungsobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "5.10.6.1",
+                    "warnedFeatures": [],
+                    "message": "Notwendige Spezifikation einer Textlichen Darstellung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.1.1.1",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation bereich",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.1.2.1",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation inhaltSoPlan",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.1.2.2",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation rasterAenderung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.1.2.3",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung der Relation gehoertZuPlan",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.1.3.1",
+                    "warnedFeatures": [],
+                    "message": "Rückwärts-Referenzen auf Plan-Bereiche",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.1.3.2",
+                    "warnedFeatures": [],
+                    "message": "SOPlan-Inhalte dürfen nicht gleichzeitig als originärer Planinhalt und nachrichtliche Übernahme in den Plan integriert werden.",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.1.4.1",
+                    "warnedFeatures": [],
+                    "message": "Nur Flächenobjekte der Basisebene gehören zum Flächenschluss",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.1.4.2",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung auf Flächengeometrie",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.1.5.1",
+                    "warnedFeatures": [],
+                    "message": "Nur Flächenobjekte der Basisebene gehören zum Flächenschluss",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.1.5.2",
+                    "warnedFeatures": [],
+                    "message": "Angabe des Attributs flaechenschluss bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.1.6.1",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung auf Liniengeometrie",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.1.7.1",
+                    "warnedFeatures": [],
+                    "message": "Einschränkung auf Punktgeometrie",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.2.1.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.2.1.2",
+                    "warnedFeatures": [],
+                    "message": "Überlagerungsobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.2.2.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.2.2.2",
+                    "warnedFeatures": [],
+                    "message": "Überlagerungsobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.2.3.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.2.4.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.2.5.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute artDerFestlegung und besondereArtDerFestlegung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.2.5.2",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute artDerFestlegung, besondereArtDerFestlegung und detailArtDerFestlegung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.2.5.3",
+                    "warnedFeatures": [],
+                    "message": "Flächenschlussobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.2.6.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.2.7.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.2.7.2",
+                    "warnedFeatures": [],
+                    "message": "Flächenschlussobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.2.8.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.3.1.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.3.1.2",
+                    "warnedFeatures": [],
+                    "message": "Überlagerungsobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.3.2.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.3.2.2",
+                    "warnedFeatures": [],
+                    "message": "Überlagerungsobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.3.3.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.3.3.2",
+                    "warnedFeatures": [],
+                    "message": "Überlagerungsobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.4.1.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz der Attribute gebietsArt und sonstGebietsArt",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.4.1.2",
+                    "warnedFeatures": [],
+                    "message": "Überlagerungsobjekt bei flächenhaftem Raumbezug",
+                    "erroredFeatures": []
+                },
+                {
+                    "isValid": true,
+                    "name": "6.5.1.1",
+                    "warnedFeatures": [],
+                    "message": "Konsistenz von typ und sonstTyp",
+                    "erroredFeatures": []
+                }
+            ]
+        },
+        "geometrisch": {
+            "valid": false,
+            "warnings": [],
+            "errors": [
+                "XPlanAuszug (Zeile 1, Spalte 1): 2.2.2.1: äußerer Ring verwendet falsche Laufrichtung (CW)."
+            ]
+        }
+    },
+    "bbox": {
+        "minY": 52.33234200586314,
+        "minX": 7.373668092967802,
+        "crs": "EPSG:4326",
+        "maxY": 52.33376312995529,
+        "maxX": 7.377600099759094
+    },
+    "name": "edfd613e-b85d-4ea6-9b97-bb33712b1ba6",
+    "version": "XPLAN_41",
+    "documentSummary": [
+        {
+            "name": "Nr. 108 Holstener Weg",
+            "type": "BP_Plan"
+        }
+    ],
+    "status": "Die Validierung wurde ausgeführt."
+}
\ No newline at end of file
diff --git a/xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report2.expected.xml b/xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report2.expected.xml
new file mode 100644
index 0000000000..ec4936d5d6
--- /dev/null
+++ b/xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report2.expected.xml
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><validationReport><version>XPLAN_41</version><name>996c971b-d70d-439e-add8-3a17681022c8</name><documentSummary><name>Nr. 108 Holstener Weg</name><type>BP_Plan</type></documentSummary><bbox><minX>7.373668092967802</minX><minY>52.33234200586314</minY><maxX>7.377600099759094</maxX><maxY>52.33376312995529</maxY><crs>EPSG:4326</crs></bbox><date>2024-07-26T10:16:16.136+02:00</date><valid>false</valid><status>Die Validierung wurde ausgeführt.</status><rulesMetadata><version>1.1.9</version><source>https://gitlab.opencode.de/xleitstelle/xplanung/validierungsregeln/standard/-/tree/v1.1.9</source></rulesMetadata><validationResult><geometrisch><valid>false</valid><errors>XPlanAuszug (Zeile 1, Spalte 1): 2.2.2.1: äußerer Ring verwendet falsche Laufrichtung (CW).</errors></geometrisch><semantisch><valid>true</valid><rules><isValid>true</isValid><message>Verwendung vorgegebenen URNs für das uom-Attribut von GML-MeasureType</message><name>2.1.2.1</name></rules><rules><isValid>true</isValid><message>Angabe eines Standard CRS</message><name>2.1.3.1</name></rules><rules><isValid>true</isValid><message>Flächenschlussbedingung</message><name>2.2.1.1</name></rules><rules><isValid>true</isValid><message>Relationen auf Text-Abschnitte</message><name>3.1.1.1</name></rules><rules><isValid>true</isValid><message>Relationen auf Begründungs-Abschnitte</message><name>3.1.1.2</name></rules><rules><isValid>true</isValid><message>Relation auf Präsentationsobjekte</message><name>3.1.2.1</name></rules><rules><isValid>true</isValid><message>Relation auf Fachobjekte</message><name>3.1.2.2</name></rules><rules><isValid>true</isValid><message>Relation auf Basis-Rasterplan</message><name>3.1.2.3</name></rules><rules><isValid>true</isValid><message>Relationen auf Text-Abschnitte</message><name>3.1.3.1</name></rules><rules><isValid>true</isValid><message>Relationen auf Begründungs-Abschnitte</message><name>3.1.3.2</name></rules><rules><isValid>true</isValid><message>Rückwärts-Referenzen auf Plan-Bereiche</message><name>3.1.3.3</name></rules><rules><isValid>true</isValid><message>Rückwärts-Referenzen auf Präsentationsobjekte</message><name>3.1.3.4</name></rules><rules><isValid>true</isValid><message>Spezifikation des Textinhalts</message><name>3.2.1.1</name></rules><rules><isValid>true</isValid><message>Spezifikation des Textinhalts</message><name>3.2.2.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der verschiedenen Höhenangaben</message><name>3.2.3.1</name></rules><rules><isValid>true</isValid><message>Verwendung von Höhenangaben, die sich auf eine auf Bezugshöhe beziehen, die auf Planebene definiert ist</message><name>3.2.3.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute hoehenbezug und abweichenderHoehenbezug</message><name>3.2.3.3</name></rules><rules><isValid>true</isValid><message>Verweis auf Dokumente.</message><name>3.2.4.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute ags (Amtlicher Gemeindeschlüssel) und rs (Regionalschlüssel).</message><name>3.2.5.1</name></rules><rules><isValid>true</isValid><message>Spezifikation des Fachobjekt-Attributs bei nicht-freien Präsentationsobjekten</message><name>3.3.1.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute art und index</message><name>3.3.1.2</name></rules><rules><isValid>true</isValid><message>Rückwärts-Referenzen auf Plan-Bereiche</message><name>3.3.1.3</name></rules><rules><isValid>true</isValid><message>Einschränkung des Raumbezugs auf Punktgeometrie.</message><name>3.3.2.1</name></rules><rules><isValid>true</isValid><message>Einschränkung des Raumbezugs auf Liniengeometrie.</message><name>3.3.3.1</name></rules><rules><isValid>true</isValid><message>Einschränkung des Raumbezugs auf Flächengeometrie.</message><name>3.3.4.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation bereich</message><name>4.1.1.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation inhaltBPlan</message><name>4.1.2.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation rasterAenderung</message><name>4.1.2.2</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation gehoertZuPlan</message><name>4.1.2.3</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation wirdAusgeglichenDurchFlaeche</message><name>4.1.3.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation wirdAusgeglichenDurchMassnahme</message><name>4.1.3.2</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation wirdAusgeglichenDurchSPEMassnahme</message><name>4.1.3.3</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation wirdAusgeglichenDurchSPEFlaeche</message><name>4.1.3.4</name></rules><rules><isValid>true</isValid><message>Rückwärts-Referenzen auf Plan-Bereiche</message><name>4.1.3.5</name></rules><rules><isValid>true</isValid><message>BPlan-Inhalte dürfen nicht gleichzeitig als originärer Planinhalt und nachrichtliche Übernahme in den Plan integriert werden.</message><name>4.1.3.6</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation wirdAusgeglichenDurchABE</message><name>4.1.3.7</name></rules><rules><isValid>true</isValid><message>Nur Flächenobjekte der Basisebene gehören zum Flächenschluss</message><name>4.1.4.1</name></rules><rules><isValid>true</isValid><message>Einschränkung auf Flächengeometrie</message><name>4.1.4.2</name></rules><rules><isValid>true</isValid><message>Nur Flächenobjekte der Basisebene gehören zum Flächenschluss</message><name>4.1.5.1</name></rules><rules><isValid>true</isValid><message>Angabe des Attributs flaechenschluss bei flächenhaftem Raumbezug</message><name>4.1.5.2</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekte gehören nie zum Flächenschluss.</message><name>4.1.6.1</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekte auf Ebene 0 gehören immer zum Flächenschluss</message><name>4.1.7.1</name></rules><rules><isValid>true</isValid><message>Einschränkung auf Liniengeometrie</message><name>4.1.8.1</name></rules><rules><isValid>true</isValid><message>Einschränkung auf Punktgeometrie</message><name>4.1.9.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur GFZ</message><name>4.2.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur GF</message><name>4.2.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur GFZ und GF</message><name>4.2.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur BMZ</message><name>4.2.4</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur BM</message><name>4.2.5</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur BMZ und BM</message><name>4.2.6</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur GRZ</message><name>4.2.7</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur GR</message><name>4.2.8</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur GRZ und GR</message><name>4.2.9</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zu Z</message><name>4.2.10</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zu ZU</message><name>4.2.11</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur Dachneigung</message><name>4.3.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute dachform und detaillierteDachform</message><name>4.3.2</name></rules><rules><isValid>true</isValid><message>Relation abweichungText</message><name>4.5.1.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute allgArtDerBaulNutzung und besondereArtDerBaulNutzung</message><name>4.5.1.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute besondereArtDerBaulNutzung und sondernutzung</message><name>4.5.1.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute bauweise und abweichendeBauweise</message><name>4.5.1.4</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute detaillierteArtDer BaulNutzung, allgArtDerBaulNutzung, besondereArtDerBaulNutzung und sondernutzung</message><name>4.5.1.5</name></rules><rules><isValid>true</isValid><message>Relation baugrenze</message><name>4.5.2.1</name></rules><rules><isValid>true</isValid><message>Relation baulinie</message><name>4.5.2.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute typ und sonstTyp</message><name>4.5.10.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.5.13.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>4.5.13.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>4.5.13.3</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.5.14.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>4.5.14.2</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation eigentümer</message><name>4.5.14.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>4.5.14.4</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>4.5.15.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>4.6.3.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.7.1.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen</message><name>4.7.1.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>4.7.1.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung</message><name>4.7.1.4</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi (i = 1, 2, 3, 4)</message><name>4.7.1.5</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung</message><name>4.7.1.6</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.7.2.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>4.7.2.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>4.7.2.3</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.8.1.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>4.8.1.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>4.8.1.3</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.8.2.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>4.8.2.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>4.8.2.3</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekt bei flächenhaftem Raumbezug</message><name>4.8.2.4</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.8.3.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen</message><name>4.8.3.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>4.8.3.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung</message><name>4.8.3.4</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi</message><name>4.8.3.5</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung</message><name>4.8.3.6</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute massnahme und weitereMassnahme1</message><name>4.9.2.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereMassnahme2und weitereMassnahme1</message><name>4.9.2.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen</message><name>4.9.2.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute massnahme und weitereMassnahme1</message><name>4.9.3.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereMassnahme2und weitereMassnahme1</message><name>4.9.3.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen</message><name>4.9.3.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute massnahme und weitereMassnahme1</message><name>4.9.5.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereMassnahme2und weitereMassnahme1</message><name>4.9.5.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen</message><name>4.9.5.3</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>4.9.5.4</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>4.9.6.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>4.10.2.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.11.1.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen</message><name>4.11.1.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>4.11.1.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung</message><name>4.11.1.4</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi</message><name>4.11.1.5</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung</message><name>4.11.1.6</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekt bei flächenhaftem Raumbezug</message><name>4.11.1.7</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation begrenzungslinie</message><name>4.12.1.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation begrenzungslinie</message><name>4.12.2.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>4.12.2.2</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>4.12.3.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung</message><name>4.13.1.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung</message><name>4.13.2.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.14.1.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>4.14.2.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute startWinkel und endWinkel</message><name>4.14.3.1</name></rules><rules><isValid>true</isValid><message>Kein flächenhafter Raumbezug</message><name>4.14.3.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>4.14.4.1</name></rules><rules><isValid>true</isValid><message>Notwendige Spezifikation einer Textlichen Darstellung</message><name>4.14.6.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Relation hoehenangabe</message><name>4.14.7.1</name></rules><rules><isValid>true</isValid><message>Kein flächenhafter Raumbezug</message><name>4.14.7.2</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation bereich</message><name>5.1.1.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute planArt und sonstPlanArt</message><name>5.1.1.2</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation inhaltFPlan</message><name>5.1.2.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation rasterAenderung</message><name>5.1.2.2</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation gehoertZuPlan</message><name>5.1.2.3</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation wirdAusgeglichenDurchFlaeche</message><name>5.1.3.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation wirdAusgeglichenDurchSPE</message><name>5.1.3.2</name></rules><rules><isValid>true</isValid><message>Rückwärts-Referenzen auf Plan-Bereiche</message><name>5.1.3.3</name></rules><rules><isValid>true</isValid><message>FPlan-Inhalte dürfen nicht gleichzeitig als originärer Planinhalt und nachrichtliche Übernahme in den Plan integriert werden.</message><name>5.1.3.4</name></rules><rules><isValid>true</isValid><message>Nur Flächenobjekte der Basisebene gehören zum Flächenschluss</message><name>5.1.4.1</name></rules><rules><isValid>true</isValid><message>Einschränkung auf Flächengeometrie</message><name>5.1.4.2</name></rules><rules><isValid>true</isValid><message>Nur Flächenobjekte der Basisebene gehören zum Flächenschluss</message><name>5.1.5.1</name></rules><rules><isValid>true</isValid><message>Angabe des Attributs flaechenschluss bei flächenhaftem Raumbezug</message><name>5.1.5.2</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekte gehören nie zum Flächenschluss</message><name>5.1.6.1</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekte der Ebene 0 gehören zum Flächenschluss</message><name>5.1.7.1</name></rules><rules><isValid>true</isValid><message>Einschränkung auf Liniengeometrie</message><name>5.1.8.1</name></rules><rules><isValid>true</isValid><message>Einschränkung auf Punktgeometrie</message><name>5.1.9.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute allgArtDerBaulNutzung und besondereArtDerBaulNutzung</message><name>5.3.1.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute besondereArtDerBaulNutzung und sonderNutzung</message><name>5.3.1.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute detaillierteArtDer BaulNutzung, allgArtDerBaulNutzung, besondereArtDerBaulNutzung und sonderNutzung</message><name>5.3.1.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Angaben zur GFZ</message><name>5.3.1.4</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>5.4.1.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen</message><name>5.4.1.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>5.4.1.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung</message><name>5.4.1.4</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi (i = 1, 2, 3, 4, 5)</message><name>5.4.1.5</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung</message><name>5.4.1.6</name></rules><rules><isValid>true</isValid><message>Einschränkung des Raumbezugs</message><name>5.4.1.7</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekt bei flächenhaftem Raumbezug</message><name>5.4.1.8</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>5.4.2.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation einer einzigen detaillierter Zweckbestimmung</message><name>5.4.2.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>5.4.2.3</name></rules><rules><isValid>true</isValid><message>Einschränkung des Raumbezugs</message><name>5.4.2.4</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekt bei flächenhaftem Raumbezug</message><name>5.4.2.5</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>5.5.1.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>5.5.1.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>5.5.1.3</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>5.5.2.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>5.5.2.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>5.5.2.3</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>5.5.3.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen</message><name>5.5.3.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>5.5.3.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung</message><name>5.5.3.4</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi (i = 1, 2, 3, 4, 5)</message><name>5.5.3.5</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung</message><name>5.5.3.6</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekt bei flächenhaftem Raumbezug</message><name>5.5.3.7</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute massnahme, weitereMassnahme1 und weitereMassnahme2</message><name>5.6.1.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen</message><name>5.6.1.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute massnahme, weitereMassnahme1 und weitereMassnahme2</message><name>5.6.2.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen</message><name>5.6.2.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>5.7.1.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen</message><name>5.7.1.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen</message><name>5.7.1.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung</message><name>5.7.1.4</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereZweckbestimmungi und weitereBesondZweckbestimmungi (i = 1, 2, 3)</message><name>5.7.1.5</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung</message><name>5.7.1.6</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekt bei flächenhaftem Raumbezug</message><name>5.7.1.7</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung</message><name>5.8.1.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung</message><name>5.8.1.2</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>5.8.1.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>5.9.1.1</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekt bei flächenhaftem Raumbezug</message><name>5.9.1.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung</message><name>5.9.2.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>5.9.2.2</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>5.10.1.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>5.10.2.1</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen</message><name>5.10.2.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung</message><name>5.10.2.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute weitereZweckbestimmungi und weitereBesondZweckbestimmungi (i = 1, 2)</message><name>5.10.2.4</name></rules><rules><isValid>true</isValid><message>Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen</message><name>5.10.3.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>5.10.4.1</name></rules><rules><isValid>true</isValid><message>Notwendige Spezifikation einer Textlichen Darstellung</message><name>5.10.6.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation bereich</message><name>6.1.1.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation inhaltSoPlan</message><name>6.1.2.1</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation rasterAenderung</message><name>6.1.2.2</name></rules><rules><isValid>true</isValid><message>Einschränkung der Relation gehoertZuPlan</message><name>6.1.2.3</name></rules><rules><isValid>true</isValid><message>Rückwärts-Referenzen auf Plan-Bereiche</message><name>6.1.3.1</name></rules><rules><isValid>true</isValid><message>SOPlan-Inhalte dürfen nicht gleichzeitig als originärer Planinhalt und nachrichtliche Übernahme in den Plan integriert werden.</message><name>6.1.3.2</name></rules><rules><isValid>true</isValid><message>Nur Flächenobjekte der Basisebene gehören zum Flächenschluss</message><name>6.1.4.1</name></rules><rules><isValid>true</isValid><message>Einschränkung auf Flächengeometrie</message><name>6.1.4.2</name></rules><rules><isValid>true</isValid><message>Nur Flächenobjekte der Basisebene gehören zum Flächenschluss</message><name>6.1.5.1</name></rules><rules><isValid>true</isValid><message>Angabe des Attributs flaechenschluss bei flächenhaftem Raumbezug</message><name>6.1.5.2</name></rules><rules><isValid>true</isValid><message>Einschränkung auf Liniengeometrie</message><name>6.1.6.1</name></rules><rules><isValid>true</isValid><message>Einschränkung auf Punktgeometrie</message><name>6.1.7.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.2.1.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>6.2.1.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.2.2.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>6.2.2.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.2.3.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.2.4.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und besondereArtDerFestlegung</message><name>6.2.5.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung, besondereArtDerFestlegung und detailArtDerFestlegung</message><name>6.2.5.2</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekt bei flächenhaftem Raumbezug</message><name>6.2.5.3</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.2.6.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.2.7.1</name></rules><rules><isValid>true</isValid><message>Flächenschlussobjekt bei flächenhaftem Raumbezug</message><name>6.2.7.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.2.8.1</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.3.1.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>6.3.1.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.3.2.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>6.3.2.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung</message><name>6.3.3.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>6.3.3.2</name></rules><rules><isValid>true</isValid><message>Konsistenz der Attribute gebietsArt und sonstGebietsArt</message><name>6.4.1.1</name></rules><rules><isValid>true</isValid><message>Überlagerungsobjekt bei flächenhaftem Raumbezug</message><name>6.4.1.2</name></rules><rules><isValid>true</isValid><message>Konsistenz von typ und sonstTyp</message><name>6.5.1.1</name></rules></semantisch><syntaktisch><valid>true</valid></syntaktisch></validationResult></validationReport>
\ No newline at end of file
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
new file mode 100644
index 0000000000..847c3dbb47
--- /dev/null
+++ b/xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report6.expected.json
@@ -0,0 +1 @@
+{"documentSummary":[{"name":"Nr. 108 Holstener Weg","type":"BP_Plan"}],"version":"XPLAN_41","filename":null,"name":"8dc3163c-a361-49b8-9c53-3733f7d61274","bbox":{"minX":7.373668092967802,"minY":52.33234200586314,"maxX":7.377600099759094,"maxY":52.33376312995529,"crs":"EPSG:4326"},"date":"2024-07-26T10:16:30.191+0200","valid":false,"status":"Die Validierung wurde ausgeführt.","externalReferences":[],"externalReferencesResult":[],"rulesMetadata":{"version":"1.1.9","source":"https://gitlab.opencode.de/xleitstelle/xplanung/validierungsregeln/standard/-/tree/v1.1.9"},"validationResult":{"semantisch":{"valid":true,"rules":[{"name":"2.1.2.1","isValid":true,"message":"Verwendung vorgegebenen URNs für das uom-Attribut von GML-MeasureType","warnedFeatures":[],"erroredFeatures":[]},{"name":"2.1.3.1","isValid":true,"message":"Angabe eines Standard CRS","warnedFeatures":[],"erroredFeatures":[]},{"name":"2.2.1.1","isValid":true,"message":"Flächenschlussbedingung","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.1.1.1","isValid":true,"message":"Relationen auf Text-Abschnitte","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.1.1.2","isValid":true,"message":"Relationen auf Begründungs-Abschnitte","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.1.2.1","isValid":true,"message":"Relation auf Präsentationsobjekte","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.1.2.2","isValid":true,"message":"Relation auf Fachobjekte","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.1.2.3","isValid":true,"message":"Relation auf Basis-Rasterplan","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.1.3.1","isValid":true,"message":"Relationen auf Text-Abschnitte","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.1.3.2","isValid":true,"message":"Relationen auf Begründungs-Abschnitte","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.1.3.3","isValid":true,"message":"Rückwärts-Referenzen auf Plan-Bereiche","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.1.3.4","isValid":true,"message":"Rückwärts-Referenzen auf Präsentationsobjekte","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.2.1.1","isValid":true,"message":"Spezifikation des Textinhalts","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.2.2.1","isValid":true,"message":"Spezifikation des Textinhalts","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.2.3.1","isValid":true,"message":"Konsistenz der verschiedenen Höhenangaben","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.2.3.2","isValid":true,"message":"Verwendung von Höhenangaben, die sich auf eine auf Bezugshöhe beziehen, die auf Planebene definiert ist","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.2.3.3","isValid":true,"message":"Konsistenz der Attribute hoehenbezug und abweichenderHoehenbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.2.4.1","isValid":true,"message":"Verweis auf Dokumente.","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.2.5.1","isValid":true,"message":"Konsistenz der Attribute ags (Amtlicher Gemeindeschlüssel) und rs (Regionalschlüssel).","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.3.1.1","isValid":true,"message":"Spezifikation des Fachobjekt-Attributs bei nicht-freien Präsentationsobjekten","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.3.1.2","isValid":true,"message":"Konsistenz der Attribute art und index","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.3.1.3","isValid":true,"message":"Rückwärts-Referenzen auf Plan-Bereiche","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.3.2.1","isValid":true,"message":"Einschränkung des Raumbezugs auf Punktgeometrie.","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.3.3.1","isValid":true,"message":"Einschränkung des Raumbezugs auf Liniengeometrie.","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.3.4.1","isValid":true,"message":"Einschränkung des Raumbezugs auf Flächengeometrie.","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.1.1","isValid":true,"message":"Einschränkung der Relation bereich","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.2.1","isValid":true,"message":"Einschränkung der Relation inhaltBPlan","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.2.2","isValid":true,"message":"Einschränkung der Relation rasterAenderung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.2.3","isValid":true,"message":"Einschränkung der Relation gehoertZuPlan","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.3.1","isValid":true,"message":"Einschränkung der Relation wirdAusgeglichenDurchFlaeche","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.3.2","isValid":true,"message":"Einschränkung der Relation wirdAusgeglichenDurchMassnahme","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.3.3","isValid":true,"message":"Einschränkung der Relation wirdAusgeglichenDurchSPEMassnahme","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.3.4","isValid":true,"message":"Einschränkung der Relation wirdAusgeglichenDurchSPEFlaeche","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.3.5","isValid":true,"message":"Rückwärts-Referenzen auf Plan-Bereiche","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.3.6","isValid":true,"message":"BPlan-Inhalte dürfen nicht gleichzeitig als originärer Planinhalt und nachrichtliche Übernahme in den Plan integriert werden.","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.3.7","isValid":true,"message":"Einschränkung der Relation wirdAusgeglichenDurchABE","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.4.1","isValid":true,"message":"Nur Flächenobjekte der Basisebene gehören zum Flächenschluss","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.4.2","isValid":true,"message":"Einschränkung auf Flächengeometrie","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.5.1","isValid":true,"message":"Nur Flächenobjekte der Basisebene gehören zum Flächenschluss","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.5.2","isValid":true,"message":"Angabe des Attributs flaechenschluss bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.6.1","isValid":true,"message":"Überlagerungsobjekte gehören nie zum Flächenschluss.","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.7.1","isValid":true,"message":"Flächenschlussobjekte auf Ebene 0 gehören immer zum Flächenschluss","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.8.1","isValid":true,"message":"Einschränkung auf Liniengeometrie","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.9.1","isValid":true,"message":"Einschränkung auf Punktgeometrie","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.1","isValid":true,"message":"Konsistenz der Angaben zur GFZ","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.2","isValid":true,"message":"Konsistenz der Angaben zur GF","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.3","isValid":true,"message":"Konsistenz der Angaben zur GFZ und GF","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.4","isValid":true,"message":"Konsistenz der Angaben zur BMZ","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.5","isValid":true,"message":"Konsistenz der Angaben zur BM","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.6","isValid":true,"message":"Konsistenz der Angaben zur BMZ und BM","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.7","isValid":true,"message":"Konsistenz der Angaben zur GRZ","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.8","isValid":true,"message":"Konsistenz der Angaben zur GR","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.9","isValid":true,"message":"Konsistenz der Angaben zur GRZ und GR","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.10","isValid":true,"message":"Konsistenz der Angaben zu Z","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.11","isValid":true,"message":"Konsistenz der Angaben zu ZU","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.3.1","isValid":true,"message":"Konsistenz der Angaben zur Dachneigung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.3.2","isValid":true,"message":"Konsistenz der Attribute dachform und detaillierteDachform","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.1.1","isValid":true,"message":"Relation abweichungText","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.1.2","isValid":true,"message":"Konsistenz der Attribute allgArtDerBaulNutzung und besondereArtDerBaulNutzung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.1.3","isValid":true,"message":"Konsistenz der Attribute besondereArtDerBaulNutzung und sondernutzung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.1.4","isValid":true,"message":"Konsistenz der Attribute bauweise und abweichendeBauweise","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.1.5","isValid":true,"message":"Konsistenz der Attribute detaillierteArtDer BaulNutzung, allgArtDerBaulNutzung, besondereArtDerBaulNutzung und sondernutzung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.2.1","isValid":true,"message":"Relation baugrenze","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.2.2","isValid":true,"message":"Relation baulinie","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.10.1","isValid":true,"message":"Konsistenz der Attribute typ und sonstTyp","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.13.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.13.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.13.3","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.14.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.14.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.14.3","isValid":true,"message":"Einschränkung der Relation eigentümer","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.14.4","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.15.1","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.6.3.1","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.7.1.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.7.1.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.7.1.3","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.7.1.4","isValid":true,"message":"Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.7.1.5","isValid":true,"message":"Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi (i = 1, 2, 3, 4)","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.7.1.6","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.7.2.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.7.2.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.7.2.3","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.1.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.1.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.1.3","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.2.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.2.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.2.3","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.2.4","isValid":true,"message":"Flächenschlussobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.3.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.3.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.3.3","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.3.4","isValid":true,"message":"Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.3.5","isValid":true,"message":"Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.3.6","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.2.1","isValid":true,"message":"Konsistenz der Attribute massnahme und weitereMassnahme1","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.2.2","isValid":true,"message":"Konsistenz der Attribute weitereMassnahme2und weitereMassnahme1","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.2.3","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.3.1","isValid":true,"message":"Konsistenz der Attribute massnahme und weitereMassnahme1","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.3.2","isValid":true,"message":"Konsistenz der Attribute weitereMassnahme2und weitereMassnahme1","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.3.3","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.5.1","isValid":true,"message":"Konsistenz der Attribute massnahme und weitereMassnahme1","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.5.2","isValid":true,"message":"Konsistenz der Attribute weitereMassnahme2und weitereMassnahme1","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.5.3","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.5.4","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.6.1","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.10.2.1","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.11.1.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.11.1.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.11.1.3","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.11.1.4","isValid":true,"message":"Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.11.1.5","isValid":true,"message":"Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.11.1.6","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.11.1.7","isValid":true,"message":"Flächenschlussobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.12.1.1","isValid":true,"message":"Einschränkung der Relation begrenzungslinie","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.12.2.1","isValid":true,"message":"Einschränkung der Relation begrenzungslinie","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.12.2.2","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.12.3.1","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.13.1.1","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.13.2.1","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.14.1.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.14.2.1","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.14.3.1","isValid":true,"message":"Konsistenz der Attribute startWinkel und endWinkel","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.14.3.2","isValid":true,"message":"Kein flächenhafter Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.14.4.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.14.6.1","isValid":true,"message":"Notwendige Spezifikation einer Textlichen Darstellung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.14.7.1","isValid":true,"message":"Verwendung der Relation hoehenangabe","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.14.7.2","isValid":true,"message":"Kein flächenhafter Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.1.1","isValid":true,"message":"Einschränkung der Relation bereich","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.1.2","isValid":true,"message":"Konsistenz der Attribute planArt und sonstPlanArt","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.2.1","isValid":true,"message":"Einschränkung der Relation inhaltFPlan","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.2.2","isValid":true,"message":"Einschränkung der Relation rasterAenderung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.2.3","isValid":true,"message":"Einschränkung der Relation gehoertZuPlan","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.3.1","isValid":true,"message":"Einschränkung der Relation wirdAusgeglichenDurchFlaeche","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.3.2","isValid":true,"message":"Einschränkung der Relation wirdAusgeglichenDurchSPE","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.3.3","isValid":true,"message":"Rückwärts-Referenzen auf Plan-Bereiche","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.3.4","isValid":true,"message":"FPlan-Inhalte dürfen nicht gleichzeitig als originärer Planinhalt und nachrichtliche Übernahme in den Plan integriert werden.","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.4.1","isValid":true,"message":"Nur Flächenobjekte der Basisebene gehören zum Flächenschluss","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.4.2","isValid":true,"message":"Einschränkung auf Flächengeometrie","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.5.1","isValid":true,"message":"Nur Flächenobjekte der Basisebene gehören zum Flächenschluss","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.5.2","isValid":true,"message":"Angabe des Attributs flaechenschluss bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.6.1","isValid":true,"message":"Überlagerungsobjekte gehören nie zum Flächenschluss","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.7.1","isValid":true,"message":"Flächenschlussobjekte der Ebene 0 gehören zum Flächenschluss","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.8.1","isValid":true,"message":"Einschränkung auf Liniengeometrie","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.9.1","isValid":true,"message":"Einschränkung auf Punktgeometrie","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.3.1.1","isValid":true,"message":"Konsistenz der Attribute allgArtDerBaulNutzung und besondereArtDerBaulNutzung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.3.1.2","isValid":true,"message":"Konsistenz der Attribute besondereArtDerBaulNutzung und sonderNutzung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.3.1.3","isValid":true,"message":"Konsistenz der Attribute detaillierteArtDer BaulNutzung, allgArtDerBaulNutzung, besondereArtDerBaulNutzung und sonderNutzung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.3.1.4","isValid":true,"message":"Konsistenz der Angaben zur GFZ","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.1.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.1.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.1.3","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.1.4","isValid":true,"message":"Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.1.5","isValid":true,"message":"Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi (i = 1, 2, 3, 4, 5)","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.1.6","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.1.7","isValid":true,"message":"Einschränkung des Raumbezugs","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.1.8","isValid":true,"message":"Flächenschlussobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.2.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.2.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation einer einzigen detaillierter Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.2.3","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.2.4","isValid":true,"message":"Einschränkung des Raumbezugs","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.2.5","isValid":true,"message":"Flächenschlussobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.1.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.1.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.1.3","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.2.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.2.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.2.3","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.3.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.3.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.3.3","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.3.4","isValid":true,"message":"Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.3.5","isValid":true,"message":"Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi (i = 1, 2, 3, 4, 5)","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.3.6","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.3.7","isValid":true,"message":"Flächenschlussobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.6.1.1","isValid":true,"message":"Konsistenz der Attribute massnahme, weitereMassnahme1 und weitereMassnahme2","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.6.1.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.6.2.1","isValid":true,"message":"Konsistenz der Attribute massnahme, weitereMassnahme1 und weitereMassnahme2","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.6.2.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.7.1.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.7.1.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.7.1.3","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.7.1.4","isValid":true,"message":"Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.7.1.5","isValid":true,"message":"Konsistenz der Attribute weitereZweckbestimmungi und weitereBesondZweckbestimmungi (i = 1, 2, 3)","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.7.1.6","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.7.1.7","isValid":true,"message":"Flächenschlussobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.8.1.1","isValid":true,"message":"Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.8.1.2","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.8.1.3","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.9.1.1","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.9.1.2","isValid":true,"message":"Flächenschlussobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.9.2.1","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.9.2.2","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.10.1.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.10.2.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.10.2.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.10.2.3","isValid":true,"message":"Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.10.2.4","isValid":true,"message":"Konsistenz der Attribute weitereZweckbestimmungi und weitereBesondZweckbestimmungi (i = 1, 2)","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.10.3.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.10.4.1","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.10.6.1","isValid":true,"message":"Notwendige Spezifikation einer Textlichen Darstellung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.1.1","isValid":true,"message":"Einschränkung der Relation bereich","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.2.1","isValid":true,"message":"Einschränkung der Relation inhaltSoPlan","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.2.2","isValid":true,"message":"Einschränkung der Relation rasterAenderung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.2.3","isValid":true,"message":"Einschränkung der Relation gehoertZuPlan","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.3.1","isValid":true,"message":"Rückwärts-Referenzen auf Plan-Bereiche","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.3.2","isValid":true,"message":"SOPlan-Inhalte dürfen nicht gleichzeitig als originärer Planinhalt und nachrichtliche Übernahme in den Plan integriert werden.","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.4.1","isValid":true,"message":"Nur Flächenobjekte der Basisebene gehören zum Flächenschluss","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.4.2","isValid":true,"message":"Einschränkung auf Flächengeometrie","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.5.1","isValid":true,"message":"Nur Flächenobjekte der Basisebene gehören zum Flächenschluss","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.5.2","isValid":true,"message":"Angabe des Attributs flaechenschluss bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.6.1","isValid":true,"message":"Einschränkung auf Liniengeometrie","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.7.1","isValid":true,"message":"Einschränkung auf Punktgeometrie","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.1.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.1.2","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.2.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.2.2","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.3.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.4.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.5.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und besondereArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.5.2","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung, besondereArtDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.5.3","isValid":true,"message":"Flächenschlussobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.6.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.7.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.7.2","isValid":true,"message":"Flächenschlussobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.8.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.3.1.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.3.1.2","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.3.2.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.3.2.2","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.3.3.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.3.3.2","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.4.1.1","isValid":true,"message":"Konsistenz der Attribute gebietsArt und sonstGebietsArt","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.4.1.2","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.5.1.1","isValid":true,"message":"Konsistenz von typ und sonstTyp","warnedFeatures":[],"erroredFeatures":[]}]},"geometrisch":{"valid":false,"errors":["XPlanAuszug (Zeile 1, Spalte 1): 2.2.2.1: äußerer Ring verwendet falsche Laufrichtung (CW)."],"warnings":[]},"syntaktisch":{"valid":true,"messages":[]},"profile":[{"name":"test1","description":"description1","ergebnis":{"valid":false,"rules":[]}}]}}
\ No newline at end of file
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
new file mode 100644
index 0000000000..0e22c169b5
--- /dev/null
+++ b/xplan-validator/xplan-validator-executor/src/test/resources/de/latlon/xplanbox/validator/executor/report7.expected.json
@@ -0,0 +1 @@
+{"documentSummary":[{"name":"Nr. 108 Holstener Weg","type":"BP_Plan"}],"version":"XPLAN_41","filename":null,"name":"6463c72f-4a7d-40d0-a129-3de95fdd0eb8","bbox":{"minX":7.373668092967802,"minY":52.33234200586314,"maxX":7.377600099759094,"maxY":52.33376312995529,"crs":"EPSG:4326"},"date":"2024-07-26T10:16:25.697+0200","valid":false,"status":"Die Validierung wurde ausgeführt.","externalReferences":[],"externalReferencesResult":[],"rulesMetadata":{"version":"1.1.9","source":"https://gitlab.opencode.de/xleitstelle/xplanung/validierungsregeln/standard/-/tree/v1.1.9"},"validationResult":{"semantisch":{"valid":true,"rules":[{"name":"2.1.2.1","isValid":true,"message":"Verwendung vorgegebenen URNs für das uom-Attribut von GML-MeasureType","warnedFeatures":[],"erroredFeatures":[]},{"name":"2.1.3.1","isValid":true,"message":"Angabe eines Standard CRS","warnedFeatures":[],"erroredFeatures":[]},{"name":"2.2.1.1","isValid":true,"message":"Flächenschlussbedingung","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.1.1.1","isValid":true,"message":"Relationen auf Text-Abschnitte","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.1.1.2","isValid":true,"message":"Relationen auf Begründungs-Abschnitte","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.1.2.1","isValid":true,"message":"Relation auf Präsentationsobjekte","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.1.2.2","isValid":true,"message":"Relation auf Fachobjekte","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.1.2.3","isValid":true,"message":"Relation auf Basis-Rasterplan","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.1.3.1","isValid":true,"message":"Relationen auf Text-Abschnitte","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.1.3.2","isValid":true,"message":"Relationen auf Begründungs-Abschnitte","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.1.3.3","isValid":true,"message":"Rückwärts-Referenzen auf Plan-Bereiche","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.1.3.4","isValid":true,"message":"Rückwärts-Referenzen auf Präsentationsobjekte","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.2.1.1","isValid":true,"message":"Spezifikation des Textinhalts","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.2.2.1","isValid":true,"message":"Spezifikation des Textinhalts","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.2.3.1","isValid":true,"message":"Konsistenz der verschiedenen Höhenangaben","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.2.3.2","isValid":true,"message":"Verwendung von Höhenangaben, die sich auf eine auf Bezugshöhe beziehen, die auf Planebene definiert ist","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.2.3.3","isValid":true,"message":"Konsistenz der Attribute hoehenbezug und abweichenderHoehenbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.2.4.1","isValid":true,"message":"Verweis auf Dokumente.","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.2.5.1","isValid":true,"message":"Konsistenz der Attribute ags (Amtlicher Gemeindeschlüssel) und rs (Regionalschlüssel).","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.3.1.1","isValid":true,"message":"Spezifikation des Fachobjekt-Attributs bei nicht-freien Präsentationsobjekten","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.3.1.2","isValid":true,"message":"Konsistenz der Attribute art und index","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.3.1.3","isValid":true,"message":"Rückwärts-Referenzen auf Plan-Bereiche","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.3.2.1","isValid":true,"message":"Einschränkung des Raumbezugs auf Punktgeometrie.","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.3.3.1","isValid":true,"message":"Einschränkung des Raumbezugs auf Liniengeometrie.","warnedFeatures":[],"erroredFeatures":[]},{"name":"3.3.4.1","isValid":true,"message":"Einschränkung des Raumbezugs auf Flächengeometrie.","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.1.1","isValid":true,"message":"Einschränkung der Relation bereich","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.2.1","isValid":true,"message":"Einschränkung der Relation inhaltBPlan","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.2.2","isValid":true,"message":"Einschränkung der Relation rasterAenderung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.2.3","isValid":true,"message":"Einschränkung der Relation gehoertZuPlan","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.3.1","isValid":true,"message":"Einschränkung der Relation wirdAusgeglichenDurchFlaeche","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.3.2","isValid":true,"message":"Einschränkung der Relation wirdAusgeglichenDurchMassnahme","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.3.3","isValid":true,"message":"Einschränkung der Relation wirdAusgeglichenDurchSPEMassnahme","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.3.4","isValid":true,"message":"Einschränkung der Relation wirdAusgeglichenDurchSPEFlaeche","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.3.5","isValid":true,"message":"Rückwärts-Referenzen auf Plan-Bereiche","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.3.6","isValid":true,"message":"BPlan-Inhalte dürfen nicht gleichzeitig als originärer Planinhalt und nachrichtliche Übernahme in den Plan integriert werden.","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.3.7","isValid":true,"message":"Einschränkung der Relation wirdAusgeglichenDurchABE","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.4.1","isValid":true,"message":"Nur Flächenobjekte der Basisebene gehören zum Flächenschluss","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.4.2","isValid":true,"message":"Einschränkung auf Flächengeometrie","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.5.1","isValid":true,"message":"Nur Flächenobjekte der Basisebene gehören zum Flächenschluss","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.5.2","isValid":true,"message":"Angabe des Attributs flaechenschluss bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.6.1","isValid":true,"message":"Überlagerungsobjekte gehören nie zum Flächenschluss.","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.7.1","isValid":true,"message":"Flächenschlussobjekte auf Ebene 0 gehören immer zum Flächenschluss","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.8.1","isValid":true,"message":"Einschränkung auf Liniengeometrie","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.1.9.1","isValid":true,"message":"Einschränkung auf Punktgeometrie","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.1","isValid":true,"message":"Konsistenz der Angaben zur GFZ","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.2","isValid":true,"message":"Konsistenz der Angaben zur GF","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.3","isValid":true,"message":"Konsistenz der Angaben zur GFZ und GF","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.4","isValid":true,"message":"Konsistenz der Angaben zur BMZ","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.5","isValid":true,"message":"Konsistenz der Angaben zur BM","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.6","isValid":true,"message":"Konsistenz der Angaben zur BMZ und BM","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.7","isValid":true,"message":"Konsistenz der Angaben zur GRZ","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.8","isValid":true,"message":"Konsistenz der Angaben zur GR","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.9","isValid":true,"message":"Konsistenz der Angaben zur GRZ und GR","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.10","isValid":true,"message":"Konsistenz der Angaben zu Z","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.2.11","isValid":true,"message":"Konsistenz der Angaben zu ZU","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.3.1","isValid":true,"message":"Konsistenz der Angaben zur Dachneigung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.3.2","isValid":true,"message":"Konsistenz der Attribute dachform und detaillierteDachform","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.1.1","isValid":true,"message":"Relation abweichungText","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.1.2","isValid":true,"message":"Konsistenz der Attribute allgArtDerBaulNutzung und besondereArtDerBaulNutzung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.1.3","isValid":true,"message":"Konsistenz der Attribute besondereArtDerBaulNutzung und sondernutzung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.1.4","isValid":true,"message":"Konsistenz der Attribute bauweise und abweichendeBauweise","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.1.5","isValid":true,"message":"Konsistenz der Attribute detaillierteArtDer BaulNutzung, allgArtDerBaulNutzung, besondereArtDerBaulNutzung und sondernutzung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.2.1","isValid":true,"message":"Relation baugrenze","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.2.2","isValid":true,"message":"Relation baulinie","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.10.1","isValid":true,"message":"Konsistenz der Attribute typ und sonstTyp","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.13.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.13.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.13.3","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.14.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.14.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.14.3","isValid":true,"message":"Einschränkung der Relation eigentümer","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.14.4","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.5.15.1","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.6.3.1","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.7.1.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.7.1.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.7.1.3","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.7.1.4","isValid":true,"message":"Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.7.1.5","isValid":true,"message":"Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi (i = 1, 2, 3, 4)","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.7.1.6","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.7.2.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.7.2.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.7.2.3","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.1.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.1.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.1.3","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.2.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.2.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.2.3","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.2.4","isValid":true,"message":"Flächenschlussobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.3.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.3.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.3.3","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.3.4","isValid":true,"message":"Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.3.5","isValid":true,"message":"Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.8.3.6","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.2.1","isValid":true,"message":"Konsistenz der Attribute massnahme und weitereMassnahme1","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.2.2","isValid":true,"message":"Konsistenz der Attribute weitereMassnahme2und weitereMassnahme1","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.2.3","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.3.1","isValid":true,"message":"Konsistenz der Attribute massnahme und weitereMassnahme1","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.3.2","isValid":true,"message":"Konsistenz der Attribute weitereMassnahme2und weitereMassnahme1","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.3.3","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.5.1","isValid":true,"message":"Konsistenz der Attribute massnahme und weitereMassnahme1","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.5.2","isValid":true,"message":"Konsistenz der Attribute weitereMassnahme2und weitereMassnahme1","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.5.3","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.5.4","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.9.6.1","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.10.2.1","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.11.1.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.11.1.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.11.1.3","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.11.1.4","isValid":true,"message":"Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.11.1.5","isValid":true,"message":"Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.11.1.6","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.11.1.7","isValid":true,"message":"Flächenschlussobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.12.1.1","isValid":true,"message":"Einschränkung der Relation begrenzungslinie","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.12.2.1","isValid":true,"message":"Einschränkung der Relation begrenzungslinie","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.12.2.2","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.12.3.1","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.13.1.1","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.13.2.1","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.14.1.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.14.2.1","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.14.3.1","isValid":true,"message":"Konsistenz der Attribute startWinkel und endWinkel","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.14.3.2","isValid":true,"message":"Kein flächenhafter Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.14.4.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.14.6.1","isValid":true,"message":"Notwendige Spezifikation einer Textlichen Darstellung","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.14.7.1","isValid":true,"message":"Verwendung der Relation hoehenangabe","warnedFeatures":[],"erroredFeatures":[]},{"name":"4.14.7.2","isValid":true,"message":"Kein flächenhafter Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.1.1","isValid":true,"message":"Einschränkung der Relation bereich","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.1.2","isValid":true,"message":"Konsistenz der Attribute planArt und sonstPlanArt","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.2.1","isValid":true,"message":"Einschränkung der Relation inhaltFPlan","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.2.2","isValid":true,"message":"Einschränkung der Relation rasterAenderung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.2.3","isValid":true,"message":"Einschränkung der Relation gehoertZuPlan","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.3.1","isValid":true,"message":"Einschränkung der Relation wirdAusgeglichenDurchFlaeche","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.3.2","isValid":true,"message":"Einschränkung der Relation wirdAusgeglichenDurchSPE","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.3.3","isValid":true,"message":"Rückwärts-Referenzen auf Plan-Bereiche","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.3.4","isValid":true,"message":"FPlan-Inhalte dürfen nicht gleichzeitig als originärer Planinhalt und nachrichtliche Übernahme in den Plan integriert werden.","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.4.1","isValid":true,"message":"Nur Flächenobjekte der Basisebene gehören zum Flächenschluss","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.4.2","isValid":true,"message":"Einschränkung auf Flächengeometrie","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.5.1","isValid":true,"message":"Nur Flächenobjekte der Basisebene gehören zum Flächenschluss","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.5.2","isValid":true,"message":"Angabe des Attributs flaechenschluss bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.6.1","isValid":true,"message":"Überlagerungsobjekte gehören nie zum Flächenschluss","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.7.1","isValid":true,"message":"Flächenschlussobjekte der Ebene 0 gehören zum Flächenschluss","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.8.1","isValid":true,"message":"Einschränkung auf Liniengeometrie","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.1.9.1","isValid":true,"message":"Einschränkung auf Punktgeometrie","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.3.1.1","isValid":true,"message":"Konsistenz der Attribute allgArtDerBaulNutzung und besondereArtDerBaulNutzung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.3.1.2","isValid":true,"message":"Konsistenz der Attribute besondereArtDerBaulNutzung und sonderNutzung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.3.1.3","isValid":true,"message":"Konsistenz der Attribute detaillierteArtDer BaulNutzung, allgArtDerBaulNutzung, besondereArtDerBaulNutzung und sonderNutzung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.3.1.4","isValid":true,"message":"Konsistenz der Angaben zur GFZ","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.1.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.1.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.1.3","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.1.4","isValid":true,"message":"Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.1.5","isValid":true,"message":"Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi (i = 1, 2, 3, 4, 5)","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.1.6","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.1.7","isValid":true,"message":"Einschränkung des Raumbezugs","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.1.8","isValid":true,"message":"Flächenschlussobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.2.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.2.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation einer einzigen detaillierter Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.2.3","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.2.4","isValid":true,"message":"Einschränkung des Raumbezugs","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.4.2.5","isValid":true,"message":"Flächenschlussobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.1.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.1.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.1.3","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.2.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.2.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.2.3","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.3.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.3.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.3.3","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.3.4","isValid":true,"message":"Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.3.5","isValid":true,"message":"Konsistenz der Attribute weitereBesondZweckbestimmungi und weitereZweckbestimmungi (i = 1, 2, 3, 4, 5)","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.3.6","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.5.3.7","isValid":true,"message":"Flächenschlussobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.6.1.1","isValid":true,"message":"Konsistenz der Attribute massnahme, weitereMassnahme1 und weitereMassnahme2","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.6.1.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.6.2.1","isValid":true,"message":"Konsistenz der Attribute massnahme, weitereMassnahme1 und weitereMassnahme2","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.6.2.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Maßnahmen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.7.1.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.7.1.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.7.1.3","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer detaillierter Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.7.1.4","isValid":true,"message":"Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.7.1.5","isValid":true,"message":"Konsistenz der Attribute weitereZweckbestimmungi und weitereBesondZweckbestimmungi (i = 1, 2, 3)","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.7.1.6","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.7.1.7","isValid":true,"message":"Flächenschlussobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.8.1.1","isValid":true,"message":"Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.8.1.2","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung bzw. besondere Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.8.1.3","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.9.1.1","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.9.1.2","isValid":true,"message":"Flächenschlussobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.9.2.1","isValid":true,"message":"Konsistenz der Attribute für detaillierte Zweckbestimmung und Zweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.9.2.2","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.10.1.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.10.2.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.10.2.2","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer besonderer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.10.2.3","isValid":true,"message":"Konsistenz der Attribute zweckbestimmung und besondereZweckbestimmung","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.10.2.4","isValid":true,"message":"Konsistenz der Attribute weitereZweckbestimmungi und weitereBesondZweckbestimmungi (i = 1, 2)","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.10.3.1","isValid":true,"message":"Verwendung der Attribute zur Spezifikation mehrerer Zweckbestimmungen","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.10.4.1","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"5.10.6.1","isValid":true,"message":"Notwendige Spezifikation einer Textlichen Darstellung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.1.1","isValid":true,"message":"Einschränkung der Relation bereich","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.2.1","isValid":true,"message":"Einschränkung der Relation inhaltSoPlan","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.2.2","isValid":true,"message":"Einschränkung der Relation rasterAenderung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.2.3","isValid":true,"message":"Einschränkung der Relation gehoertZuPlan","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.3.1","isValid":true,"message":"Rückwärts-Referenzen auf Plan-Bereiche","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.3.2","isValid":true,"message":"SOPlan-Inhalte dürfen nicht gleichzeitig als originärer Planinhalt und nachrichtliche Übernahme in den Plan integriert werden.","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.4.1","isValid":true,"message":"Nur Flächenobjekte der Basisebene gehören zum Flächenschluss","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.4.2","isValid":true,"message":"Einschränkung auf Flächengeometrie","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.5.1","isValid":true,"message":"Nur Flächenobjekte der Basisebene gehören zum Flächenschluss","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.5.2","isValid":true,"message":"Angabe des Attributs flaechenschluss bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.6.1","isValid":true,"message":"Einschränkung auf Liniengeometrie","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.1.7.1","isValid":true,"message":"Einschränkung auf Punktgeometrie","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.1.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.1.2","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.2.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.2.2","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.3.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.4.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.5.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und besondereArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.5.2","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung, besondereArtDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.5.3","isValid":true,"message":"Flächenschlussobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.6.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.7.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.7.2","isValid":true,"message":"Flächenschlussobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.2.8.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.3.1.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.3.1.2","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.3.2.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.3.2.2","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.3.3.1","isValid":true,"message":"Konsistenz der Attribute artDerFestlegung und detailArtDerFestlegung","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.3.3.2","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.4.1.1","isValid":true,"message":"Konsistenz der Attribute gebietsArt und sonstGebietsArt","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.4.1.2","isValid":true,"message":"Überlagerungsobjekt bei flächenhaftem Raumbezug","warnedFeatures":[],"erroredFeatures":[]},{"name":"6.5.1.1","isValid":true,"message":"Konsistenz von typ und sonstTyp","warnedFeatures":[],"erroredFeatures":[]}]},"geometrisch":{"valid":false,"errors":["XPlanAuszug (Zeile 1, Spalte 1): 2.2.2.1: äußerer Ring verwendet falsche Laufrichtung (CW)."],"warnings":[]},"syntaktisch":{"valid":true,"messages":[]},"profile":[{"name":"test1","description":"description1","ergebnis":{"valid":false,"rules":[]}}]}}
\ No newline at end of file
diff --git a/xplan-validator/xplan-validator-executor/src/test/resources/xplan.gml b/xplan-validator/xplan-validator-executor/src/test/resources/xplan.gml
new file mode 100644
index 0000000000..07d99bfb19
--- /dev/null
+++ b/xplan-validator/xplan-validator-executor/src/test/resources/xplan.gml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+  #%L
+  xplan-validator-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%
+  -->
+
+<xplan:XPlanAuszug xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xlink="http://www.w3.org/1999/xlink"
+                   xmlns:xplan="http://www.xplanung.de/xplangml/4/1"
+                   gml:id="GML_ad5adb8f-d05d-45d2-8197-29b26f4dd142">
+    <gml:boundedBy>
+        <gml:Envelope srsName="EPSG:25832">
+            <gml:lowerCorner>389187.29 5799248.293</gml:lowerCorner>
+            <gml:upperCorner>389451.908 5799400.487</gml:upperCorner>
+        </gml:Envelope>
+    </gml:boundedBy>
+    <gml:featureMember>
+        <xplan:BP_Bereich gml:id="GML_b3cca7aa-8908-4182-bf9f-1d96e623a1c7">
+            <gml:boundedBy>
+                <gml:Envelope srsName="EPSG:25832">
+                    <gml:lowerCorner>389187.29 5799248.293</gml:lowerCorner>
+                    <gml:upperCorner>389451.908 5799400.487</gml:upperCorner>
+                </gml:Envelope>
+            </gml:boundedBy>
+            <xplan:nummer>1683</xplan:nummer>
+            <xplan:name>610-531-01/37.1</xplan:name>
+            <xplan:gehoertZuPlan xlink:href="#GML_3a07cab4-ba41-43cf-a2b2-098a099ab0c3"/>
+        </xplan:BP_Bereich>
+    </gml:featureMember>
+    <gml:featureMember>
+        <xplan:BP_Plan gml:id="GML_3a07cab4-ba41-43cf-a2b2-098a099ab0c3">
+            <gml:boundedBy>
+                <gml:Envelope srsName="EPSG:25832">
+                    <gml:lowerCorner>389187.29 5799248.293</gml:lowerCorner>
+                    <gml:upperCorner>389451.908 5799400.487</gml:upperCorner>
+                </gml:Envelope>
+            </gml:boundedBy>
+            <xplan:name>Nr. 108 Holstener Weg</xplan:name>
+            <xplan:nummer>108</xplan:nummer>
+            <xplan:beschreibung>(§ 13 BauGB)</xplan:beschreibung>
+            <xplan:technHerstellDatum>2019-01-01</xplan:technHerstellDatum>
+            <xplan:genehmigungsDatum>2019-07-15</xplan:genehmigungsDatum>
+            <xplan:erstellungsMassstab>10000</xplan:erstellungsMassstab>
+            <xplan:xPlanGMLVersion>4.1</xplan:xPlanGMLVersion>
+            <xplan:raeumlicherGeltungsbereich>
+                <gml:Polygon srsName="EPSG:25832" gml:id="GML_8ddef72c-e5d0-4633-9514-fc27286aa5bd">
+                    <gml:exterior>
+                        <gml:LinearRing>
+                            <gml:posList srsDimension="2">389187.29 5799400.487 389192.226 5799400.102 389213.987
+                                5799398.409 389228.148 5799397.301 389235.230180782 5799396.76051955 389267.224
+                                5799394.319 389280.11 5799393.347 389313.709 5799390.721 389320.31 5799390.205
+                                389322.384189298 5799390.04297999 389325.29 5799389.816 389335.943 5799388.983
+                                389338.767 5799388.73 389359.381 5799386.879 389383.682 5799382.558 389399.504
+                                5799378.591 389428.454 5799370.13900001 389431.729 5799369.183 389436.708 5799367.117
+                                389442.462 5799364.731 389444.099 5799364.052 389444.497 5799363.887 389448.589
+                                5799362.19 389450.365 5799361.454 389451.908 5799360.814 389435.775757406
+                                5799350.39333417 389420.573 5799340.573 389415.206 5799337.114 389418.749 5799302.879
+                                389419.677 5799293.894 389420.484 5799286.098 389422.311 5799268.414 389401.481518475
+                                5799266.40521146 389396.274 5799265.903 389370.273 5799263.3 389356.361 5799262.039
+                                389355.362 5799262.017 389341.745 5799262.042 389337.745 5799262.048 389323.108
+                                5799262.075 389317.236 5799262.088 389312.912346494 5799261.28406564 389303.866
+                                5799259.602 389281.835 5799255.493 389278.769 5799254.92 389271.16 5799253.497
+                                389269.442 5799253.17600001 389256.587 5799250.788 389248.612 5799249.308 389247.613
+                                5799249.119 389243.177 5799248.293 389187.29 5799400.487
+                            </gml:posList>
+                        </gml:LinearRing>
+                    </gml:exterior>
+                </gml:Polygon>
+            </xplan:raeumlicherGeltungsbereich>
+            <xplan:gemeinde>
+                <xplan:XP_Gemeinde>
+                    <xplan:ags>03454045</xplan:ags>
+                    <xplan:gemeindeName>Salzbergen</xplan:gemeindeName>
+                </xplan:XP_Gemeinde>
+            </xplan:gemeinde>
+            <xplan:planArt>9999</xplan:planArt>
+            <xplan:rechtsstand>4000</xplan:rechtsstand>
+            <xplan:auslegungsStartDatum>2019-04-01</xplan:auslegungsStartDatum>
+            <xplan:auslegungsEndDatum>2019-05-03</xplan:auslegungsEndDatum>
+            <xplan:satzungsbeschlussDatum>2019-08-25</xplan:satzungsbeschlussDatum>
+            <xplan:inkrafttretensDatum>2019-08-25</xplan:inkrafttretensDatum>
+            <xplan:bereich xlink:href="#GML_b3cca7aa-8908-4182-bf9f-1d96e623a1c7"/>
+        </xplan:BP_Plan>
+    </gml:featureMember>
+</xplan:XPlanAuszug>
diff --git a/xplan-validator/xplan-validator-storage/pom.xml b/xplan-validator/xplan-validator-storage/pom.xml
new file mode 100644
index 0000000000..bd940607d2
--- /dev/null
+++ b/xplan-validator/xplan-validator-storage/pom.xml
@@ -0,0 +1,71 @@
+<?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/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>xplan-validator-storage</artifactId>
+
+  <parent>
+    <groupId>de.latlon.product.xplanbox</groupId>
+    <artifactId>xplan-validator</artifactId>
+    <version>8.0-SNAPSHOT</version>
+  </parent>
+
+  <dependencies>
+    <!-- xPlanBox -->
+    <dependency>
+      <groupId>de.latlon.product.xplanbox</groupId>
+      <artifactId>xplan-core-commons</artifactId>
+    </dependency>
+    <!-- spring -->
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-beans</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.dataformat</groupId>
+      <artifactId>jackson-dataformat-yaml</artifactId>
+    </dependency>
+    <!-- aws -->
+    <dependency>
+      <groupId>com.amazonaws</groupId>
+      <artifactId>aws-java-sdk-s3</artifactId>
+    </dependency>
+    <!-- test -->
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.assertj</groupId>
+      <artifactId>assertj-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>io.findify</groupId>
+      <artifactId>s3mock_2.13</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>jakarta.annotation</groupId>
+      <artifactId>jakarta.annotation-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/ErrorType.java b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/ErrorType.java
new file mode 100644
index 0000000000..cdc73c021c
--- /dev/null
+++ b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/ErrorType.java
@@ -0,0 +1,34 @@
+package de.latlon.xplanbox.validator.storage;
+
+import java.util.Arrays;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+public enum ErrorType {
+
+	INVALID_REQUEST(400),
+
+	INVALID_CONTENT(422),
+
+	INTERNAL_ERROR(500);
+
+	private final int statusCode;
+
+	ErrorType(int statusCode) {
+		this.statusCode = statusCode;
+	}
+
+	public int getStatusCode() {
+		return statusCode;
+	}
+
+	public static ErrorType fromStatusCode(int statusCode) {
+		return Arrays.stream(values())
+			.filter(errorType -> errorType.statusCode == statusCode)
+			.findFirst()
+			.orElse(INTERNAL_ERROR);
+	}
+
+}
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
new file mode 100644
index 0000000000..83fd1fcc45
--- /dev/null
+++ b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/Status.java
@@ -0,0 +1,77 @@
+package de.latlon.xplanbox.validator.storage;
+
+import static de.latlon.xplanbox.validator.storage.StatusType.REQUESTED;
+
+import java.util.Date;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+public class Status {
+
+	private StatusType status;
+
+	private String errorMsg;
+
+	private ErrorType errorType;
+
+	private String linkToJsonReport;
+
+	private String linkToPdfReport;
+
+	private Date expirationTime;
+
+	public Status() {
+		this.status = REQUESTED;
+	}
+
+	public StatusType getStatus() {
+		return status;
+	}
+
+	public void setStatus(StatusType status) {
+		this.status = status;
+	}
+
+	public String getErrorMsg() {
+		return errorMsg;
+	}
+
+	public void setErrorMsg(String errorMsg) {
+		this.errorMsg = errorMsg;
+	}
+
+	public ErrorType getErrorType() {
+		return errorType;
+	}
+
+	public void setErrorType(ErrorType errorType) {
+		this.errorType = errorType;
+	}
+
+	public String getLinkToJsonReport() {
+		return linkToJsonReport;
+	}
+
+	public void setLinkToJsonReport(String linkToJsonReport) {
+		this.linkToJsonReport = linkToJsonReport;
+	}
+
+	public void setReportLinkExpirationTime(Date expirationTime) {
+		this.expirationTime = expirationTime;
+	}
+
+	public Date getExpirationTime() {
+		return expirationTime;
+	}
+
+	public void setReportLinkPdf(String linkToPdfReport) {
+		this.linkToPdfReport = linkToPdfReport;
+	}
+
+	public String getLinkToPdfReport() {
+		return linkToPdfReport;
+	}
+
+}
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
new file mode 100644
index 0000000000..6f54a92f5a
--- /dev/null
+++ b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/StatusType.java
@@ -0,0 +1,21 @@
+package de.latlon.xplanbox.validator.storage;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+public enum StatusType {
+
+	// Validation requested
+	REQUESTED,
+
+	// Validation started
+	STARTED,
+
+	// Validation failed
+	FAILED,
+
+	// Validation finished
+	FINISHED
+
+}
diff --git a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/StoredValidationReport.java b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/StoredValidationReport.java
new file mode 100644
index 0000000000..866e4b58c9
--- /dev/null
+++ b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/StoredValidationReport.java
@@ -0,0 +1,46 @@
+package de.latlon.xplanbox.validator.storage;
+
+import java.util.Date;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+public class StoredValidationReport {
+
+	private final String linkToJsonReport;
+
+	private final String linkToPdfReport;
+
+	private final Date expirationTime;
+
+	public StoredValidationReport(String linkToJsonReport, String linkToPdfReport) {
+		this(linkToJsonReport, linkToPdfReport, null);
+	}
+
+	public StoredValidationReport(String linkToJsonReport, String linkToPdfReport, Date expirationTime) {
+		this.linkToJsonReport = linkToJsonReport;
+		this.linkToPdfReport = linkToPdfReport;
+		this.expirationTime = expirationTime;
+	}
+
+	/**
+	 * @return the url the file can be accessed, never <code>null</code>
+	 */
+	public String getLinkToJsonReport() {
+		return linkToJsonReport;
+	}
+
+	public String getLinkToPdfReport() {
+		return linkToPdfReport;
+	}
+
+	/**
+	 * @return the date the objet expires, may be <code>null</code> if the file does not
+	 * expire
+	 */
+	public Date getExpirationTime() {
+		return expirationTime;
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/ValidationDetails.java b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/ValidationDetails.java
new file mode 100644
index 0000000000..467de70a37
--- /dev/null
+++ b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/ValidationDetails.java
@@ -0,0 +1,29 @@
+package de.latlon.xplanbox.validator.storage;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+public class ValidationDetails {
+
+	@JsonProperty("attachments")
+	private List<String> attachments = new ArrayList<>();
+
+	public List<String> getAttachments() {
+		return attachments;
+	}
+
+	public void setAttachments(List<String> attachments) {
+		this.attachments = attachments;
+	}
+
+	public void addAttachment(String attachments) {
+		getAttachments().add(attachments);
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/ValidationExecutionException.java b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/ValidationExecutionException.java
new file mode 100644
index 0000000000..43d1560087
--- /dev/null
+++ b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/ValidationExecutionException.java
@@ -0,0 +1,20 @@
+package de.latlon.xplanbox.validator.storage;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+public class ValidationExecutionException extends Exception {
+
+	private final ErrorType errorType;
+
+	public ValidationExecutionException(String msg, ErrorType errorType) {
+		super(msg);
+		this.errorType = errorType;
+	}
+
+	public ErrorType getErrorType() {
+		return errorType;
+	}
+
+}
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
new file mode 100644
index 0000000000..3d771f09af
--- /dev/null
+++ b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/ValidationExecutionStorage.java
@@ -0,0 +1,238 @@
+package de.latlon.xplanbox.validator.storage;
+
+import static de.latlon.xplanbox.validator.storage.StatusType.FAILED;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+import de.latlon.xplan.commons.archive.XPlanArchiveCreator;
+import de.latlon.xplan.commons.s3.StorageException;
+import org.apache.tika.Tika;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+public abstract class ValidationExecutionStorage {
+
+	public static final String APPLICATION_YAML = "application/yaml";
+
+	public enum FileType {
+
+		PLAN(""), DETAILS("_details.yaml"), STATUS("_status.yaml");
+
+		private final String suffix;
+
+		FileType(String suffix) {
+			this.suffix = suffix;
+		}
+
+		public String getSuffix() {
+			return suffix;
+		}
+
+	}
+
+	public enum ReportType {
+
+		JSON(".json"), PDF(".pdf"), ZIP(".zip");
+
+		private final String fileExtension;
+
+		ReportType(String fileExtension) {
+			this.fileExtension = fileExtension;
+		}
+
+		public static ReportType byFileExtension(String fileExtension) {
+			Optional<ReportType> reportType = Arrays.stream(values())
+				.filter(rt -> rt.fileExtension.equals(fileExtension))
+				.findFirst();
+			return reportType.orElseThrow(
+					() -> new IllegalArgumentException("Could not find ReportType with fileExtension" + fileExtension));
+		}
+
+		public String getFileExtension() {
+			return fileExtension;
+		}
+
+	}
+
+	static public class Key {
+
+		private String fileName;
+
+		Key(String uuid, FileType fileType) {
+			this.fileName = uuid + fileType.getSuffix();
+		}
+
+		public Key(String uuid, ReportType reportType) {
+			this.fileName = uuid + "_report" + reportType.getFileExtension();
+		}
+
+		public String toFileName() {
+			return fileName;
+		}
+
+		public static Key details(String uuid) {
+			return new Key(uuid, FileType.DETAILS);
+		}
+
+		public static Key status(String uuid) {
+			return new Key(uuid, FileType.STATUS);
+		}
+
+		public static Key plan(String uuid) {
+			return new Key(uuid, FileType.PLAN);
+		}
+
+		public static Key report(String uuid, ReportType reportType) {
+			return new Key(uuid, reportType);
+		}
+
+	}
+
+	public String addPlanToValidate(Path plan) throws IOException, StorageException {
+		String uuid = UUID.randomUUID().toString();
+		ValidationDetails validationDetails = createValidationDetails(plan);
+		byte[] serializedValidationDetails = serialize(validationDetails);
+		addToStore(Key.details(uuid), APPLICATION_YAML, serializedValidationDetails);
+		addToStore(Key.status(uuid), APPLICATION_YAML, serialize(new Status()));
+		addToStore(Key.plan(uuid), plan);
+		return uuid;
+	}
+
+	public void cleanupAfterValidation(String uuid) throws StorageException {
+		removeFromStore(Key.details(uuid));
+		removeFromStore(Key.plan(uuid));
+	}
+
+	public Status retrieveStatus(String uuid) throws StorageException {
+		byte[] content = retrieveContent(Key.status(uuid));
+		return deserialize(content);
+	}
+
+	public void changeStatus(String uuid, StatusType statusType) throws StorageException {
+		changeStatus(uuid, statusType, null);
+	}
+
+	public void changeStatus(String uuid, String errorMsg, ErrorType errorType) throws StorageException {
+		Status status = retrieveStatus(uuid);
+		status.setStatus(FAILED);
+		status.setErrorMsg(errorMsg);
+		status.setErrorType(errorType);
+		addToStore(Key.status(uuid), APPLICATION_YAML, serialize(status));
+	}
+
+	public void changeStatus(String uuid, StatusType statusType, StoredValidationReport storedValidationReport)
+			throws StorageException {
+		Status status = retrieveStatus(uuid);
+		status.setStatus(statusType);
+		if (storedValidationReport != null) {
+			status.setLinkToJsonReport(storedValidationReport.getLinkToJsonReport());
+			status.setReportLinkPdf(storedValidationReport.getLinkToPdfReport());
+			status.setReportLinkExpirationTime(storedValidationReport.getExpirationTime());
+		}
+		addToStore(Key.status(uuid), APPLICATION_YAML, serialize(status));
+	}
+
+	public byte[] retrieveReport(String uuid, ReportType reportType)
+			throws StorageException, ValidationExecutionException {
+		Status status = retrieveStatus(uuid);
+		if (status.getStatus() == FAILED)
+			throw new ValidationExecutionException(status.getErrorMsg(), status.getErrorType());
+		return retrieveContent(Key.report(uuid, reportType));
+	}
+
+	/**
+	 * @param key of the file to return, never <code>null</code>
+	 * @return the content of the file, never <code>null</code>
+	 * @throws StorageException if an error occured retrieving the file or the file does
+	 * not exist
+	 */
+	protected abstract byte[] retrieveContent(Key key) throws StorageException;
+
+	protected abstract void addToStore(Key key, String contentType, byte[] file) throws StorageException;
+
+	protected abstract void addToStore(Key key, Path file) throws IOException, StorageException;
+
+	protected abstract void removeFromStore(Key key) throws StorageException;
+
+	/**
+	 * ugly name to improve
+	 * @throws IOException
+	 */
+	public abstract void writePlanToValidate(String uuid, Path toPath) throws IOException, StorageException;
+
+	/**
+	 * ugly name to improve
+	 * @return
+	 * @throws IOException
+	 */
+	public abstract StoredValidationReport saveValidationResult(String uuid, Map<ReportType, Path> reports)
+			throws IOException, StorageException;
+
+	private ValidationDetails createValidationDetails(Path plan) throws IOException {
+		ValidationDetails validationDetails = new ValidationDetails();
+		if (isZipFile(plan)) {
+			try (ZipFile zipFile = new ZipFile(plan.toFile())) {
+				Enumeration<? extends ZipEntry> entries = zipFile.entries();
+				while (entries.hasMoreElements()) {
+					ZipEntry entry = entries.nextElement();
+					validationDetails.addAttachment(entry.getName());
+				}
+			}
+		}
+		else {
+			validationDetails.addAttachment(XPlanArchiveCreator.MAIN_FILE);
+		}
+		return validationDetails;
+	}
+
+	private boolean isZipFile(Path path) throws IOException {
+		String contentType = new Tika().detect(path);
+		if ("application/zip".equals(contentType))
+			return true;
+		return false;
+	}
+
+	private byte[] serialize(ValidationDetails validationDetails) throws StorageException {
+		try {
+			ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
+			return mapper.writeValueAsBytes(validationDetails);
+		}
+		catch (JsonProcessingException e) {
+			throw new StorageException("Could not serialize ValidationDetails " + validationDetails, e);
+		}
+	}
+
+	private byte[] serialize(Status statusNotification) throws StorageException {
+		try {
+			ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
+			return mapper.writeValueAsBytes(statusNotification);
+		}
+		catch (JsonProcessingException e) {
+			throw new StorageException("Could not serialize Status " + statusNotification, e);
+		}
+	}
+
+	private Status deserialize(byte[] content) throws StorageException {
+		try {
+			ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
+			return mapper.readValue(content, Status.class);
+		}
+		catch (IOException e) {
+			throw new StorageException("Could not deserialize Status", e);
+		}
+	}
+
+}
\ No newline at end of file
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/AmazonS3Context.java
new file mode 100644
index 0000000000..e8880b26da
--- /dev/null
+++ b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/config/AmazonS3Context.java
@@ -0,0 +1,92 @@
+/*-
+ * #%L
+ * xplan-core-manager - XPlan Manager Core Komponente
+ * %%
+ * 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.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.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;
+
+/**
+ * Spring configuration for using AWS S3 as a storage.
+ *
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @author <a href="mailto:friebe@lat-lon.de">Torsten Friebe</a>
+ * @since 7.0
+ */
+@Configuration
+@Profile("s3execution")
+public class AmazonS3Context {
+
+	@Bean(destroyMethod = "shutdown")
+	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
+	public AWSCredentials credentials(@Value("${xplanbox.s3.accessKeyId}") String accessKeyId,
+			@Value("${xplanbox.s3.secretKey}") String secretKey) {
+		return new BasicAWSCredentials(accessKeyId, secretKey);
+	}
+
+	@Bean
+	public ValidationExecutionStorage validationExecutionStorage(S3Storage s3Storage,
+			@Value("${xplanbox.validation.s3.bucketPublicUrl}") String s3PublicUrl) {
+		return new S3PlanValidationExecutionStorage(s3Storage, s3PublicUrl);
+	}
+
+	@Bean
+	public S3Storage s3Storage(AmazonS3 s3Client, @Value("${xplanbox.validation.s3.bucketName}") String bucketName)
+			throws StorageException {
+		S3Storage s3Storage = new S3Storage(s3Client, bucketName);
+		s3Storage.setBucketExpirationDate("deleteAfter30d", 30);
+		return 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
new file mode 100644
index 0000000000..54517fa677
--- /dev/null
+++ b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/filesystem/FileSystemValidationExecutionStorage.java
@@ -0,0 +1,89 @@
+package de.latlon.xplanbox.validator.storage.filesystem;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+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.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());
+	}
+
+}
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
new file mode 100644
index 0000000000..897e2458e1
--- /dev/null
+++ b/xplan-validator/xplan-validator-storage/src/main/java/de/latlon/xplanbox/validator/storage/s3/S3PlanValidationExecutionStorage.java
@@ -0,0 +1,84 @@
+package de.latlon.xplanbox.validator.storage.s3;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import com.amazonaws.services.s3.model.PutObjectResult;
+import com.amazonaws.services.s3.model.S3ObjectSummary;
+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.StoredValidationReport;
+import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+public class S3PlanValidationExecutionStorage extends ValidationExecutionStorage {
+
+	private final S3Storage s3Storage;
+
+	private final String s3PublicUrl;
+
+	public S3PlanValidationExecutionStorage(S3Storage s3Storage, String s3PublicUrl) {
+		this.s3Storage = s3Storage;
+		this.s3PublicUrl = s3PublicUrl;
+	}
+
+	@Override
+	protected byte[] retrieveContent(Key key) throws StorageException {
+		S3Object object = s3Storage.getObject(key.toFileName());
+		return object.getContent();
+	}
+
+	@Override
+	protected void addToStore(Key key, String contentType, byte[] content) throws StorageException {
+		S3Metadata s3Metadata = new S3Metadata(key.toFileName(), contentType, content.length);
+		S3Object s3Object = new S3Object(s3Metadata, content);
+		s3Storage.insertObject(s3Object);
+	}
+
+	@Override
+	protected void addToStore(Key key, Path file) throws StorageException {
+		s3Storage.insertObject(key.toFileName(), file);
+	}
+
+	@Override
+	protected void removeFromStore(Key key) {
+		S3ObjectSummary object = new S3ObjectSummary();
+		object.setKey(key.toFileName());
+		s3Storage.deleteObject(object);
+	}
+
+	@Override
+	public void writePlanToValidate(String uuid, Path toPath) throws StorageException {
+		Key key = Key.plan(uuid);
+		S3Object object = s3Storage.getObject(key.toFileName());
+		try {
+			Files.copy(new ByteArrayInputStream(object.getContent()), toPath);
+		}
+		catch (IOException e) {
+			throw new StorageException("Could not write plan to file" + toPath, e);
+		}
+	}
+
+	@Override
+	public StoredValidationReport saveValidationResult(String uuid, Map<ReportType, Path> reports)
+			throws StorageException {
+		PutObjectResult lastPutObjectResult = null;
+		for (Entry<ReportType, Path> entry : reports.entrySet()) {
+			String fileName = Key.report(uuid, entry.getKey()).toFileName();
+			lastPutObjectResult = s3Storage.insertObject(fileName, entry.getValue());
+		}
+		String reportLinkToJson = s3PublicUrl + "/" + Key.report(uuid, ReportType.JSON).toFileName();
+		String reportLinkToPdf = s3PublicUrl + "/" + Key.report(uuid, ReportType.PDF).toFileName();
+		return new StoredValidationReport(reportLinkToJson, reportLinkToPdf, lastPutObjectResult.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
new file mode 100644
index 0000000000..44c27343f1
--- /dev/null
+++ b/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/filesystem/FileSystemValidationExecutionStorageStorageTest.java
@@ -0,0 +1,75 @@
+package de.latlon.xplanbox.validator.storage.filesystem;
+
+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()));
+
+		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()));
+
+		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/AmazonS3TestContext.java b/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/AmazonS3TestContext.java
new file mode 100644
index 0000000000..5e224f92b5
--- /dev/null
+++ b/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/AmazonS3TestContext.java
@@ -0,0 +1,88 @@
+/*-
+ * #%L
+ * xplan-core-manager - XPlan Manager Core Komponente
+ * %%
+ * 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.validator.storage.s3;
+
+import com.amazonaws.auth.AWSStaticCredentialsProvider;
+import com.amazonaws.auth.AnonymousAWSCredentials;
+import com.amazonaws.client.builder.AwsClientBuilder;
+import com.amazonaws.services.s3.AmazonS3;
+import com.amazonaws.services.s3.AmazonS3ClientBuilder;
+import io.findify.s3mock.S3Mock;
+import jakarta.annotation.PreDestroy;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.annotation.Profile;
+import org.springframework.test.util.TestSocketUtils;
+
+/**
+ * Spring Configuration to enable usage of mock objects for integration tests.
+ *
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @author <a href="mailto:friebe@lat-lon.de">Torsten Friebe</a>
+ */
+@Configuration
+public class AmazonS3TestContext {
+
+	@Autowired(required = false)
+	private S3Mock s3Mock;
+
+	@Autowired
+	private AmazonS3 s3TestClient;
+
+	private final int port = TestSocketUtils.findAvailableTcpPort();
+
+	@Bean
+	@Profile("mock")
+	public S3Mock s3Mock() {
+		S3Mock s3Mock = new S3Mock.Builder().withPort(port).withInMemoryBackend().build();
+		s3Mock.start();
+		return s3Mock;
+	}
+
+	@Bean
+	@Primary
+	@Profile("mock")
+	public AmazonS3 s3TestClient(@Value("${xplanbox.s3.region}") String signingRegion,
+			@Value("${xplanbox.validation.s3.bucketName}") String bucketName,
+			@Value("${xplanbox.s3.endpoint.url}") String url) {
+		AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration(url + ":" + port,
+				signingRegion);
+		AmazonS3 client = AmazonS3ClientBuilder.standard()
+			.withPathStyleAccessEnabled(true)
+			.withEndpointConfiguration(endpoint)
+			.withCredentials(new AWSStaticCredentialsProvider(new AnonymousAWSCredentials()))
+			.build();
+		client.createBucket(bucketName);
+		return client;
+	}
+
+	@PreDestroy
+	public void shutdown() {
+		s3TestClient.shutdown();
+		if (s3Mock != null) {
+			s3Mock.stop();
+		}
+	}
+
+}
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
new file mode 100644
index 0000000000..d9ea4d9c86
--- /dev/null
+++ b/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/S3ValidationExecutionStorageIT.java
@@ -0,0 +1,87 @@
+package de.latlon.xplanbox.validator.storage.s3;
+
+import static de.latlon.xplanbox.validator.storage.ErrorType.INTERNAL_ERROR;
+import static de.latlon.xplanbox.validator.storage.StatusType.FINISHED;
+import static de.latlon.xplanbox.validator.storage.StatusType.REQUESTED;
+import static de.latlon.xplanbox.validator.storage.StatusType.STARTED;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Paths;
+
+import de.latlon.xplan.commons.s3.StorageException;
+import de.latlon.xplanbox.validator.storage.ErrorType;
+import de.latlon.xplanbox.validator.storage.Status;
+import de.latlon.xplanbox.validator.storage.StoredValidationReport;
+import de.latlon.xplanbox.validator.storage.ValidationExecutionException;
+import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage;
+import de.latlon.xplanbox.validator.storage.config.AmazonS3Context;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+@ExtendWith(SpringExtension.class)
+@ContextConfiguration(classes = { AmazonS3Context.class, AmazonS3TestContext.class })
+@ActiveProfiles({ "s3execution", "mock" })
+@TestPropertySource("classpath:s3Mock.properties")
+public class S3ValidationExecutionStorageIT {
+
+	@Autowired
+	private S3PlanValidationExecutionStorage validationExecutionStorage;
+
+	@Test
+	void testStatus() throws StorageException, URISyntaxException, IOException {
+		URL xplanGml = getClass().getResource("/xplan.gml");
+
+		String uuid = validationExecutionStorage.addPlanToValidate(Paths.get(xplanGml.toURI()));
+		Status statusRequested = validationExecutionStorage.retrieveStatus(uuid);
+		assertThat(statusRequested.getStatus()).isEqualTo(REQUESTED);
+
+		validationExecutionStorage.changeStatus(uuid, STARTED);
+		Status statusStarted = validationExecutionStorage.retrieveStatus(uuid);
+		assertThat(statusStarted.getStatus()).isEqualTo(STARTED);
+
+		StoredValidationReport validationReportDetails = new StoredValidationReport("http://test.org/test.json",
+				"http://test.org/test.pdf");
+		validationExecutionStorage.changeStatus(uuid, FINISHED, validationReportDetails);
+		Status statusFinished = validationExecutionStorage.retrieveStatus(uuid);
+		assertThat(statusFinished.getStatus()).isEqualTo(FINISHED);
+		assertThat(statusFinished.getLinkToJsonReport()).isEqualTo(validationReportDetails.getLinkToJsonReport());
+		assertThat(statusFinished.getLinkToPdfReport()).isEqualTo(validationReportDetails.getLinkToPdfReport());
+		assertThat(statusFinished.getExpirationTime()).isEqualTo(validationReportDetails.getExpirationTime());
+	}
+
+	@Test
+	void testAddAndCleanup() throws StorageException, URISyntaxException, IOException {
+		URL xplanGml = getClass().getResource("/xplan.gml");
+
+		String uuid = validationExecutionStorage.addPlanToValidate(Paths.get(xplanGml.toURI()));
+		validationExecutionStorage.cleanupAfterValidation(uuid);
+	}
+
+	@Test
+	void testChangeStatus_toError() throws URISyntaxException, StorageException, IOException {
+		URL xplanGml = getClass().getResource("/xplan.gml");
+		String uuid = validationExecutionStorage.addPlanToValidate(Paths.get(xplanGml.toURI()));
+
+		String errorMsg = "Error test";
+		validationExecutionStorage.changeStatus(uuid, errorMsg, INTERNAL_ERROR);
+
+		ValidationExecutionException exception = Assertions.assertThrows(ValidationExecutionException.class,
+				() -> validationExecutionStorage.retrieveReport(uuid, ValidationExecutionStorage.ReportType.JSON));
+		assertThat(exception.getErrorType()).isEqualTo(ErrorType.fromStatusCode(INTERNAL_ERROR.getStatusCode()));
+		assertThat(exception.getMessage()).isEqualTo(errorMsg);
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/S3ValidationExecutionStorageTest.java b/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/S3ValidationExecutionStorageTest.java
new file mode 100644
index 0000000000..f56ca231d4
--- /dev/null
+++ b/xplan-validator/xplan-validator-storage/src/test/java/de/latlon/xplanbox/validator/storage/s3/S3ValidationExecutionStorageTest.java
@@ -0,0 +1,111 @@
+package de.latlon.xplanbox.validator.storage.s3;
+
+import static de.latlon.xplanbox.validator.storage.ValidationExecutionStorage.FileType.DETAILS;
+import static de.latlon.xplanbox.validator.storage.ValidationExecutionStorage.FileType.STATUS;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import com.amazonaws.services.s3.AmazonS3;
+import com.amazonaws.services.s3.model.ObjectMetadata;
+import com.amazonaws.services.s3.model.PutObjectResult;
+import de.latlon.xplan.commons.s3.S3Storage;
+import de.latlon.xplan.commons.s3.StorageException;
+import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage.Key;
+import de.latlon.xplanbox.validator.storage.ValidationExecutionStorage.ReportType;
+
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+
+/**
+ * @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
+ * @since 8.0
+ */
+class S3ValidationExecutionStorageTest {
+
+	private static final String BUCKET_NAME = "xplanbox";
+
+	private static final String S3_PUBLIC_URL = "http://xplanbox.s3.eu-central-1.amazonaws.com";
+
+	@Test
+	void testAddPlanToValidate_gml() throws IOException, URISyntaxException, StorageException {
+		AmazonS3 client = spy(AmazonS3.class);
+		S3Storage s3Storage = new S3Storage(client, BUCKET_NAME);
+		S3PlanValidationExecutionStorage validationExecutionStorage = new S3PlanValidationExecutionStorage(s3Storage,
+				S3_PUBLIC_URL);
+		URL xplanGml = getClass().getResource("/xplan.gml");
+		String key = validationExecutionStorage.addPlanToValidate(Paths.get(xplanGml.toURI()));
+
+		ArgumentCaptor<String> keyCaptor = ArgumentCaptor.forClass(String.class);
+
+		verify(client, times(3)).doesBucketExistV2(eq(BUCKET_NAME));
+		verify(client, times(2)).putObject(eq(BUCKET_NAME), keyCaptor.capture(), any(InputStream.class),
+				any(ObjectMetadata.class));
+		verify(client).putObject(eq(BUCKET_NAME), keyCaptor.capture(), any(File.class));
+
+		assertThat(keyCaptor.getAllValues()).containsExactlyInAnyOrder(key, key + DETAILS.getSuffix(),
+				key + STATUS.getSuffix());
+	}
+
+	@Test
+	void testAddPlanToValidate_zip() throws IOException, URISyntaxException, StorageException {
+		AmazonS3 client = spy(AmazonS3.class);
+		S3Storage s3Storage = new S3Storage(client, BUCKET_NAME);
+		S3PlanValidationExecutionStorage validationExecutionStorage = new S3PlanValidationExecutionStorage(s3Storage,
+				S3_PUBLIC_URL);
+		URL xplanGml = getClass().getResource("/BPlan002_5-3.zip");
+		String key = validationExecutionStorage.addPlanToValidate(Paths.get(xplanGml.toURI()));
+
+		ArgumentCaptor<String> keyCaptor = ArgumentCaptor.forClass(String.class);
+
+		verify(client, times(3)).doesBucketExistV2(eq(BUCKET_NAME));
+		verify(client, times(2)).putObject(eq(BUCKET_NAME), keyCaptor.capture(), any(InputStream.class),
+				any(ObjectMetadata.class));
+		verify(client).putObject(eq(BUCKET_NAME), keyCaptor.capture(), any(File.class));
+
+		assertThat(keyCaptor.getAllValues()).containsExactlyInAnyOrder(key, key + DETAILS.getSuffix(),
+				key + STATUS.getSuffix());
+	}
+
+	@Test
+	void testSaveValidationResult() throws URISyntaxException, StorageException {
+		AmazonS3 client = spy(AmazonS3.class);
+		when(client.putObject(anyString(), anyString(), any(File.class))).thenReturn(mock(PutObjectResult.class));
+		S3Storage s3Storage = new S3Storage(client, BUCKET_NAME);
+		S3PlanValidationExecutionStorage validationExecutionStorage = new S3PlanValidationExecutionStorage(s3Storage,
+				S3_PUBLIC_URL);
+		URL xplanGml = getClass().getResource("/BPlan002_5-3.zip");
+		String uuid = UUID.randomUUID().toString();
+
+		Map<ReportType, Path> reports = new HashMap<>();
+		reports.put(ReportType.JSON, Paths.get(xplanGml.toURI()));
+		reports.put(ReportType.PDF, Paths.get(xplanGml.toURI()));
+		validationExecutionStorage.saveValidationResult(uuid, reports);
+
+		ArgumentCaptor<String> keyCaptor = ArgumentCaptor.forClass(String.class);
+
+		verify(client, times(2)).doesBucketExistV2(eq(BUCKET_NAME));
+		verify(client, times(2)).putObject(eq(BUCKET_NAME), keyCaptor.capture(), any(File.class));
+
+		assertThat(keyCaptor.getAllValues()).containsExactlyInAnyOrder(Key.report(uuid, ReportType.PDF).toFileName(),
+				Key.report(uuid, ReportType.JSON).toFileName());
+	}
+
+}
diff --git a/xplan-validator/xplan-validator-storage/src/test/resources/BPlan002_5-3.zip b/xplan-validator/xplan-validator-storage/src/test/resources/BPlan002_5-3.zip
new file mode 100644
index 0000000000000000000000000000000000000000..e68a0a9a42a7f9247e54484a768f2e49ec2bf261
GIT binary patch
literal 60474
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%0D9rbsrOT@
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
D8bwE4

literal 0
HcmV?d00001

diff --git a/xplan-validator/xplan-validator-storage/src/test/resources/s3Mock.properties b/xplan-validator/xplan-validator-storage/src/test/resources/s3Mock.properties
new file mode 100644
index 0000000000..d858dfb28a
--- /dev/null
+++ b/xplan-validator/xplan-validator-storage/src/test/resources/s3Mock.properties
@@ -0,0 +1,25 @@
+###
+# #%L
+# xplan-manager-core - XPlan Manager Core Komponente
+# %%
+# 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%
+###
+xplanbox.s3.accessKeyId=
+xplanbox.s3.secretKey=
+xplanbox.s3.region=eu-central-1
+xplanbox.s3.endpoint.url=http://localhost
+xplanbox.validation.s3.bucketName=latlonxpbexecution
diff --git a/xplan-validator/xplan-validator-storage/src/test/resources/xplan.gml b/xplan-validator/xplan-validator-storage/src/test/resources/xplan.gml
new file mode 100644
index 0000000000..07d99bfb19
--- /dev/null
+++ b/xplan-validator/xplan-validator-storage/src/test/resources/xplan.gml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+  #%L
+  xplan-validator-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%
+  -->
+
+<xplan:XPlanAuszug xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xlink="http://www.w3.org/1999/xlink"
+                   xmlns:xplan="http://www.xplanung.de/xplangml/4/1"
+                   gml:id="GML_ad5adb8f-d05d-45d2-8197-29b26f4dd142">
+    <gml:boundedBy>
+        <gml:Envelope srsName="EPSG:25832">
+            <gml:lowerCorner>389187.29 5799248.293</gml:lowerCorner>
+            <gml:upperCorner>389451.908 5799400.487</gml:upperCorner>
+        </gml:Envelope>
+    </gml:boundedBy>
+    <gml:featureMember>
+        <xplan:BP_Bereich gml:id="GML_b3cca7aa-8908-4182-bf9f-1d96e623a1c7">
+            <gml:boundedBy>
+                <gml:Envelope srsName="EPSG:25832">
+                    <gml:lowerCorner>389187.29 5799248.293</gml:lowerCorner>
+                    <gml:upperCorner>389451.908 5799400.487</gml:upperCorner>
+                </gml:Envelope>
+            </gml:boundedBy>
+            <xplan:nummer>1683</xplan:nummer>
+            <xplan:name>610-531-01/37.1</xplan:name>
+            <xplan:gehoertZuPlan xlink:href="#GML_3a07cab4-ba41-43cf-a2b2-098a099ab0c3"/>
+        </xplan:BP_Bereich>
+    </gml:featureMember>
+    <gml:featureMember>
+        <xplan:BP_Plan gml:id="GML_3a07cab4-ba41-43cf-a2b2-098a099ab0c3">
+            <gml:boundedBy>
+                <gml:Envelope srsName="EPSG:25832">
+                    <gml:lowerCorner>389187.29 5799248.293</gml:lowerCorner>
+                    <gml:upperCorner>389451.908 5799400.487</gml:upperCorner>
+                </gml:Envelope>
+            </gml:boundedBy>
+            <xplan:name>Nr. 108 Holstener Weg</xplan:name>
+            <xplan:nummer>108</xplan:nummer>
+            <xplan:beschreibung>(§ 13 BauGB)</xplan:beschreibung>
+            <xplan:technHerstellDatum>2019-01-01</xplan:technHerstellDatum>
+            <xplan:genehmigungsDatum>2019-07-15</xplan:genehmigungsDatum>
+            <xplan:erstellungsMassstab>10000</xplan:erstellungsMassstab>
+            <xplan:xPlanGMLVersion>4.1</xplan:xPlanGMLVersion>
+            <xplan:raeumlicherGeltungsbereich>
+                <gml:Polygon srsName="EPSG:25832" gml:id="GML_8ddef72c-e5d0-4633-9514-fc27286aa5bd">
+                    <gml:exterior>
+                        <gml:LinearRing>
+                            <gml:posList srsDimension="2">389187.29 5799400.487 389192.226 5799400.102 389213.987
+                                5799398.409 389228.148 5799397.301 389235.230180782 5799396.76051955 389267.224
+                                5799394.319 389280.11 5799393.347 389313.709 5799390.721 389320.31 5799390.205
+                                389322.384189298 5799390.04297999 389325.29 5799389.816 389335.943 5799388.983
+                                389338.767 5799388.73 389359.381 5799386.879 389383.682 5799382.558 389399.504
+                                5799378.591 389428.454 5799370.13900001 389431.729 5799369.183 389436.708 5799367.117
+                                389442.462 5799364.731 389444.099 5799364.052 389444.497 5799363.887 389448.589
+                                5799362.19 389450.365 5799361.454 389451.908 5799360.814 389435.775757406
+                                5799350.39333417 389420.573 5799340.573 389415.206 5799337.114 389418.749 5799302.879
+                                389419.677 5799293.894 389420.484 5799286.098 389422.311 5799268.414 389401.481518475
+                                5799266.40521146 389396.274 5799265.903 389370.273 5799263.3 389356.361 5799262.039
+                                389355.362 5799262.017 389341.745 5799262.042 389337.745 5799262.048 389323.108
+                                5799262.075 389317.236 5799262.088 389312.912346494 5799261.28406564 389303.866
+                                5799259.602 389281.835 5799255.493 389278.769 5799254.92 389271.16 5799253.497
+                                389269.442 5799253.17600001 389256.587 5799250.788 389248.612 5799249.308 389247.613
+                                5799249.119 389243.177 5799248.293 389187.29 5799400.487
+                            </gml:posList>
+                        </gml:LinearRing>
+                    </gml:exterior>
+                </gml:Polygon>
+            </xplan:raeumlicherGeltungsbereich>
+            <xplan:gemeinde>
+                <xplan:XP_Gemeinde>
+                    <xplan:ags>03454045</xplan:ags>
+                    <xplan:gemeindeName>Salzbergen</xplan:gemeindeName>
+                </xplan:XP_Gemeinde>
+            </xplan:gemeinde>
+            <xplan:planArt>9999</xplan:planArt>
+            <xplan:rechtsstand>4000</xplan:rechtsstand>
+            <xplan:auslegungsStartDatum>2019-04-01</xplan:auslegungsStartDatum>
+            <xplan:auslegungsEndDatum>2019-05-03</xplan:auslegungsEndDatum>
+            <xplan:satzungsbeschlussDatum>2019-08-25</xplan:satzungsbeschlussDatum>
+            <xplan:inkrafttretensDatum>2019-08-25</xplan:inkrafttretensDatum>
+            <xplan:bereich xlink:href="#GML_b3cca7aa-8908-4182-bf9f-1d96e623a1c7"/>
+        </xplan:BP_Plan>
+    </gml:featureMember>
+</xplan:XPlanAuszug>
diff --git a/xplan-webservices/xplan-webservices-validator-wms/src/test/resources/de/latlon/xplan/validator/wms/libs.expected.txt b/xplan-webservices/xplan-webservices-validator-wms/src/test/resources/de/latlon/xplan/validator/wms/libs.expected.txt
index 33c42d2c13..1341834ed6 100644
--- a/xplan-webservices/xplan-webservices-validator-wms/src/test/resources/de/latlon/xplan/validator/wms/libs.expected.txt
+++ b/xplan-webservices/xplan-webservices-validator-wms/src/test/resources/de/latlon/xplan/validator/wms/libs.expected.txt
@@ -3,6 +3,9 @@ angus-activation-2.0.2.jar
 antlr-runtime-3.5.3.jar
 apache-mime4j-core-0.8.6.jar
 asm-9.6.jar
+aws-java-sdk-core-1.12.765.jar
+aws-java-sdk-kms-1.12.765.jar
+aws-java-sdk-s3-1.12.765.jar
 axiom-api-1.4.0.jar
 axiom-impl-1.4.0.jar
 batik-anim-1.17.jar
@@ -36,6 +39,7 @@ commons-fileupload2-core-2.0.0-M2.jar
 commons-fileupload2-jakarta-servlet6-2.0.0-M2.jar
 commons-io-2.16.1.jar
 commons-lang-2.6.jar
+commons-logging-1.1.3.jar
 commons-math-2.2.jar
 commons-pool2-2.12.0.jar
 com.sun.xml.bind-jaxb-core-4.0.5.jar
@@ -117,6 +121,7 @@ istack-commons-runtime-4.1.2.jar
 jackson-annotations-2.17.2.jar
 jackson-core-2.17.2.jar
 jackson-databind-2.17.2.jar
+jackson-dataformat-cbor-2.17.2.jar
 jackson-dataformat-yaml-2.17.2.jar
 jai-codec-1.1.3.jar
 jai-core-1.1.3.jar
@@ -140,6 +145,8 @@ jaxb-runtime-4.0.5.jar
 jaxen-2.0.0.jar
 jcl-over-slf4j-2.0.13.jar
 jgridshift-core-1.3.1.jar
+jmespath-java-1.12.765.jar
+joda-time-2.12.7.jar
 jogl-1.1.2.jar
 json-path-2.9.0.jar
 json-smart-2.5.1.jar
-- 
GitLab