This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-spring-boot.git


The following commit(s) were added to refs/heads/main by this push:
     new b2a9fd0c2f8 CAMEL-18038 - add tests in camel-validator-starter (#551)
b2a9fd0c2f8 is described below

commit b2a9fd0c2f8076f3d3bec6ef7c2f745f4e920b1c
Author: Federico Mariani <34543311+cro...@users.noreply.github.com>
AuthorDate: Mon May 2 20:40:16 2022 +0200

    CAMEL-18038 - add tests in camel-validator-starter (#551)
---
 components-starter/camel-validator-starter/pom.xml |  11 +
 .../component/validator/ContextTestSupport.java    | 146 +++++++++++++
 .../validator/CustomSchemaFactoryFeatureTest.java  |  65 ++++++
 .../validator/FileValidatorRouteTest.java          | 104 +++++++++
 .../component/validator/ValidatorBeanCallTest.java |  90 ++++++++
 .../validator/ValidatorDtdAccessAbstractTest.java  |  84 ++++++++
 .../validator/ValidatorDtdAccessOffTest.java       |  85 ++++++++
 .../validator/ValidatorDtdAccessOnTest.java        |  91 ++++++++
 .../ValidatorEndpointClearCachedSchemaTest.java    | 156 ++++++++++++++
 .../validator/ValidatorIllegalImportTest.java      |  90 ++++++++
 .../ValidatorIncludeEncodingRouteTest.java         |  91 ++++++++
 .../ValidatorIncludeRelativeRouteTest.java         |  84 ++++++++
 .../validator/ValidatorIncludeRouteTest.java       | 159 ++++++++++++++
 .../validator/ValidatorLazyStartProducerTest.java  |  86 ++++++++
 .../ValidatorResourceResolverFactoryTest.java      | 223 +++++++++++++++++++
 .../component/validator/ValidatorRootPathTest.java |  76 +++++++
 .../component/validator/ValidatorRouteTest.java    | 236 +++++++++++++++++++++
 .../ValidatorWithResourceResolverRouteTest.java    | 109 ++++++++++
 .../validation/CatalogLSResourceResolver.java      | 177 ++++++++++++++++
 .../org/apache/camel/urlhandler/pd/Handler.java    |  85 ++++++++
 .../src/test/resources/jndi-example.properties     |  24 +++
 .../camel/component/validator/BroadcastMonitor.xsd |  58 +++++
 .../component/validator/BroadcastMonitorFixed.xsd  |  57 +++++
 .../apache/camel/component/validator/catalog.cat   |   2 +
 .../apache/camel/component/validator/health.xsd    |  32 +++
 .../apache/camel/component/validator/person.xsd    |  38 ++++
 .../camel/component/validator/report-base.xsd      |  48 +++++
 .../apache/camel/component/validator/report.xsd    |  36 ++++
 .../apache/camel/component/validator/schema.xsd    |  35 +++
 .../apache/camel/component/validator/sentence.xsd  |  28 +++
 .../org/apache/camel/component/validator/text.xsd  |  31 +++
 .../camel/component/validator/unsecuredSchema.xsd  |  34 +++
 .../camel/component/validator/xsds/customer.xsd    |  30 +++
 .../validator/xsds/health/common/common.xsd        |  32 +++
 .../component/validator/xsds/health/health.xsd     |  37 ++++
 .../component/validator/xsds/health/type1.xsd      |  28 +++
 .../camel/component/validator/xsds/order.xsd       |  34 +++
 .../camel/component/validator/xsds/person.xsd      |  40 ++++
 .../camel/component/validator/xsds/product.xsd     |  46 ++++
 .../camel/component/validator/xsds/type2.xsd       |  25 +++
 .../src/test/resources/report-base.xsd             |  48 +++++
 .../src/test/resources/report.xsd                  |  36 ++++
 42 files changed, 3027 insertions(+)

diff --git a/components-starter/camel-validator-starter/pom.xml 
b/components-starter/camel-validator-starter/pom.xml
index f20ba907434..eb7ef68f585 100644
--- a/components-starter/camel-validator-starter/pom.xml
+++ b/components-starter/camel-validator-starter/pom.xml
@@ -39,6 +39,17 @@
       <artifactId>camel-validator</artifactId>
       <version>${camel-version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.awaitility</groupId>
+      <artifactId>awaitility</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>xml-resolver</groupId>
+      <artifactId>xml-resolver</artifactId>
+      <version>${xml-resolver-version}</version>
+      <scope>test</scope>
+    </dependency>
     <!--START OF GENERATED CODE-->
     <dependency>
       <groupId>org.apache.camel.springboot</groupId>
diff --git 
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ContextTestSupport.java
 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ContextTestSupport.java
new file mode 100644
index 00000000000..cd5b178d9ac
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ContextTestSupport.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.NotifyBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class ContextTestSupport {
+
+       protected MockEndpoint validEndpoint;
+       protected MockEndpoint finallyEndpoint;
+       protected MockEndpoint invalidEndpoint;
+
+       protected volatile NotifyBuilder oneExchangeDone;
+
+       @Autowired
+       protected CamelContext context;
+
+       @Autowired
+       protected ProducerTemplate template;
+
+       protected boolean testDirectoryCleaned;
+
+       @AfterEach
+       public void tearDown() throws Exception {
+               testDirectoryCleaned = false;
+       }
+
+       protected Path testFile(String dir) {
+               return testDirectory().resolve(dir);
+       }
+
+       protected String fileUri() {
+               return "file:" + testDirectory();
+       }
+
+       protected String fileUri(String query) {
+               return "file:" + testDirectory() + (query.startsWith("?") ? "" 
: "/") + query;
+       }
+
+       protected Path testDirectory(String dir, boolean create) {
+               Path f = testDirectory().resolve(dir);
+               if (create) {
+                       try {
+                               Files.createDirectories(f);
+                       } catch (IOException e) {
+                               throw new IllegalStateException("Unable to 
create test directory: " + dir, e);
+                       }
+               }
+               return f;
+       }
+
+       protected Path testDirectory() {
+               return testDirectory(false);
+       }
+
+       protected Path testDirectory(boolean create) {
+               Class<?> testClass = getClass();
+               if (create) {
+                       deleteTestDirectory();
+               }
+               return testDirectory(testClass, create);
+       }
+
+       public static Path testDirectory(Class<?> testClass, boolean create) {
+               Path dir = Paths.get("target", "data", 
testClass.getSimpleName());
+               if (create) {
+                       try {
+                               Files.createDirectories(dir);
+                       } catch (IOException e) {
+                               throw new IllegalStateException("Unable to 
create test directory: " + dir, e);
+                       }
+               }
+               return dir;
+       }
+
+       public void deleteTestDirectory() {
+               if (!testDirectoryCleaned) {
+                       deleteDirectory(testDirectory().toFile());
+                       testDirectoryCleaned = true;
+               }
+       }
+
+       public static void deleteDirectory(String file) {
+               deleteDirectory(new File(file));
+       }
+
+       /**
+        * Recursively delete a directory, useful to zapping test data
+        *
+        * @param file the directory to be deleted
+        */
+       public static void deleteDirectory(File file) {
+               if (file.isDirectory()) {
+                       File[] files = file.listFiles();
+                       if (files != null) {
+                               for (File child : files) {
+                                       deleteDirectory(child);
+                               }
+                       }
+               }
+
+               file.delete();
+       }
+
+       protected NotifyBuilder event() {
+               return new NotifyBuilder(context);
+       }
+
+       public static <T> T assertIsInstanceOf(Class<T> expectedType, Object 
value) {
+               Assertions.assertNotNull(value, "Expected an instance of type: 
" + expectedType.getName() + " but was null");
+               assertTrue(expectedType.isInstance(value), "object should be a 
" + expectedType.getName() + " but was: " + value
+                               + " with type: " + value.getClass().getName());
+               return expectedType.cast(value);
+       }
+
+}
diff --git 
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/CustomSchemaFactoryFeatureTest.java
 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/CustomSchemaFactoryFeatureTest.java
new file mode 100644
index 00000000000..5dd131d5cb3
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/CustomSchemaFactoryFeatureTest.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import javax.xml.XMLConstants;
+import javax.xml.validation.SchemaFactory;
+
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+               classes = {
+                               CamelAutoConfiguration.class,
+                               CustomSchemaFactoryFeatureTest.class,
+                               
CustomSchemaFactoryFeatureTest.TestConfiguration.class
+               }
+)
+public class CustomSchemaFactoryFeatureTest extends ContextTestSupport {
+
+       // just inject the SchemaFactory as we want
+       @Test
+       public void testCustomSchemaFactory() throws Exception {
+               ValidatorComponent v = new ValidatorComponent();
+               v.setCamelContext(context);
+               v.init();
+               
v.createEndpoint("validator:org/apache/camel/component/validator/unsecuredSchema.xsd?schemaFactory=#mySchemaFactory");
+       }
+
+       @Configuration
+       class TestConfiguration {
+
+               @Bean
+               public SchemaFactory mySchemaFactory() throws 
SAXNotSupportedException, SAXNotRecognizedException {
+                       SchemaFactory mySchemaFactory = 
SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+                       
mySchemaFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
+
+                       return mySchemaFactory;
+               }
+       }
+}
diff --git 
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/FileValidatorRouteTest.java
 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/FileValidatorRouteTest.java
new file mode 100644
index 00000000000..6405ae7295e
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/FileValidatorRouteTest.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.ValidationException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.apache.camel.util.FileUtil;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                FileValidatorRouteTest.class
+        }
+)
+public class FileValidatorRouteTest extends ContextTestSupport {
+
+    @Test
+    public void testValidMessage() throws Exception {
+        validEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+
+        template.sendBodyAndHeader(fileUri(),
+                "<mail 
xmlns='http://foo.com/bar'><subject>Hey</subject><body>Hello 
world!</body></mail>", Exchange.FILE_NAME,
+                "valid.xml");
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+
+        // should be able to delete the file
+        oneExchangeDone.matchesWaitTime();
+        assertTrue(FileUtil.deleteFile(testFile("valid.xml").toFile()),
+                "Should be able to delete the file");
+    }
+
+    @Test
+    public void testInvalidMessage() throws Exception {
+        invalidEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+
+        template.sendBodyAndHeader(fileUri(),
+                "<mail xmlns='http://foo.com/bar'><body>Hello 
world!</body></mail>", Exchange.FILE_NAME, "invalid.xml");
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+
+        // should be able to delete the file
+        oneExchangeDone.matchesWaitTime();
+        assertTrue(FileUtil.deleteFile(testFile("invalid.xml").toFile()),
+                "Should be able to delete the file");
+    }
+
+    @BeforeEach
+    public void setUp() throws Exception {
+        deleteTestDirectory();
+        validEndpoint = context.getEndpoint("mock:valid", MockEndpoint.class);
+        invalidEndpoint = context.getEndpoint("mock:invalid", 
MockEndpoint.class);
+        finallyEndpoint = context.getEndpoint("mock:finally", 
MockEndpoint.class);
+
+        validEndpoint.reset();
+        invalidEndpoint.reset();
+        finallyEndpoint.reset();
+
+        oneExchangeDone = event().whenDone(1).create();
+    }
+
+    @Bean
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from(fileUri("?noop=true")).doTry()
+                        
.to("validator:org/apache/camel/component/validator/schema.xsd").to("mock:valid")
+                        
.doCatch(ValidationException.class).to("mock:invalid").doFinally().to("mock:finally").end();
+            }
+        };
+    }
+
+}
diff --git 
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorBeanCallTest.java
 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorBeanCallTest.java
new file mode 100644
index 00000000000..a9e9e1b68b3
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorBeanCallTest.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                ValidatorBeanCallTest.class
+        }
+)
+public class ValidatorBeanCallTest extends ContextTestSupport {
+
+    @Test
+    public void testCallBean() throws Exception {
+        validEndpoint.expectedMessageCount(1);
+        invalidEndpoint.expectedMessageCount(0);
+
+        template
+                .sendBody("direct:rootPath",
+                        "<report xmlns='http://foo.com/report' 
xmlns:rb='http://foo.com/report-base'><author><rb:name>Knuth</rb:name></author><content><rb:chapter><rb:subject></rb:subject>"
+                                             + 
"<rb:abstract></rb:abstract><rb:body></rb:body></rb:chapter></content></report>");
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint);
+    }
+
+    @BeforeEach
+    public void setUp() throws Exception {
+        deleteTestDirectory();
+        validEndpoint = context.getEndpoint("mock:valid", MockEndpoint.class);
+        invalidEndpoint = context.getEndpoint("mock:invalid", 
MockEndpoint.class);
+
+        validEndpoint.reset();
+        invalidEndpoint.reset();
+    }
+
+    @Bean
+    public MyValidatorBean myBean() {
+        return new MyValidatorBean();
+    }
+
+    @Bean
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                
from("direct:rootPath").to("validator:bean:myBean.loadFile").to("mock:valid");
+            }
+        };
+    }
+
+    public static class MyValidatorBean {
+
+        public InputStream loadFile() throws Exception {
+            return 
Files.newInputStream(Paths.get("src/test/resources/report.xsd"));
+        }
+
+    }
+}
diff --git 
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessAbstractTest.java
 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessAbstractTest.java
new file mode 100644
index 00000000000..d2f228e4b85
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessAbstractTest.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import org.apache.camel.ValidationException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.support.processor.validation.SchemaReader;
+
+import org.junit.jupiter.api.BeforeEach;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.net.UnknownHostException;
+
+public abstract class ValidatorDtdAccessAbstractTest extends 
ContextTestSupport {
+
+    protected MockEndpoint finallyEndpoint;
+    protected MockEndpoint invalidEndpoint;
+    protected MockEndpoint unknownHostExceptionEndpoint;
+    protected MockEndpoint validEndpoint;
+
+    protected String payloud = getPayloudPart("Hello world!");
+
+    protected String ssrfPayloud = "<!DOCTYPE roottag PUBLIC 
\"-//VSR//PENTEST//EN\" \"http://notex.isting/test\";>\n" + payloud;
+
+    protected String xxePayloud
+            = "<!DOCTYPE updateProfile [<!ENTITY file SYSTEM 
\"http://notex.istinghost/test\";>]>\n" + getPayloudPart("&file;");
+
+    private String getPayloudPart(String bodyValue) {
+        return "<mail xmlns='http://foo.com/bar'><subject>Hey</subject><body>" 
+ bodyValue + "</body></mail>";
+    }
+
+    protected abstract boolean accessExternalDTD();
+
+    @Configuration
+    class TestConfiguration {
+        @Bean
+        protected RouteBuilder createRouteBuilder() throws Exception {
+            return new RouteBuilder() {
+
+                @Override
+                public void configure() throws Exception {
+                    if(accessExternalDTD()) {
+                        
getContext().getGlobalOptions().put(SchemaReader.ACCESS_EXTERNAL_DTD, "true");
+                    }
+                    
from("direct:start").doTry().to("validator:org/apache/camel/component/validator/schema.xsd").to("mock:valid")
+                            
.doCatch(ValidationException.class).to("mock:invalid")
+                            
.doCatch(UnknownHostException.class).to("mock:unknownHostException").doFinally().to("mock:finally")
+                            .end();
+                }
+            };
+        }
+    }
+
+    @BeforeEach
+    public void before() {
+        validEndpoint = context.getEndpoint("mock:valid", MockEndpoint.class);
+        invalidEndpoint = context.getEndpoint("mock:invalid", 
MockEndpoint.class);
+        finallyEndpoint = context.getEndpoint("mock:finally", 
MockEndpoint.class);
+        unknownHostExceptionEndpoint = 
context.getEndpoint("mock:unknownHostException", MockEndpoint.class);
+
+        validEndpoint.reset();
+        invalidEndpoint.reset();
+        finallyEndpoint.reset();
+        unknownHostExceptionEndpoint.reset();
+    }
+
+}
diff --git 
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOffTest.java
 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOffTest.java
new file mode 100644
index 00000000000..7b0d2437c26
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOffTest.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.net.UnknownHostException;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.camel.ValidationException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.support.processor.validation.SchemaReader;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                ValidatorDtdAccessOffTest.class,
+                ValidatorDtdAccessAbstractTest.TestConfiguration.class
+        }
+)
+public class ValidatorDtdAccessOffTest extends ValidatorDtdAccessAbstractTest {
+
+    /** Tests that no external DTD call is executed for StringSource. */
+    @Test
+    public void testInvalidMessageWithExternalDTDStringSource() throws 
Exception {
+        invalidEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+
+        template.sendBody("direct:start", ssrfPayloud);
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, 
unknownHostExceptionEndpoint, finallyEndpoint);
+    }
+
+    /** Tests that external DTD call is not executed for StreamSource. */
+    @Test
+    public void testInvalidMessageWithExternalDTDStreamSource() throws 
Exception {
+        invalidEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+        InputStream is = new 
ByteArrayInputStream(ssrfPayloud.getBytes(StandardCharsets.UTF_8));
+        template.sendBody("direct:start", is);
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, 
unknownHostExceptionEndpoint, finallyEndpoint);
+    }
+
+    /** Tests that XXE is not possible for StreamSource. */
+    @Test
+    public void testInvalidMessageXXESourceStream() throws Exception {
+        invalidEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+        InputStream is = new 
ByteArrayInputStream(xxePayloud.getBytes(StandardCharsets.UTF_8));
+        template.sendBody("direct:start", is);
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, 
unknownHostExceptionEndpoint, finallyEndpoint);
+    }
+
+    @Override
+    protected boolean accessExternalDTD() {
+        return false;
+    }
+}
diff --git 
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOnTest.java
 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOnTest.java
new file mode 100644
index 00000000000..ac370aabba4
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorDtdAccessOnTest.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.net.UnknownHostException;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.camel.ValidationException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.support.processor.validation.SchemaReader;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                ValidatorDtdAccessOnTest.class,
+                ValidatorDtdAccessAbstractTest.TestConfiguration.class
+        }
+)
+public class ValidatorDtdAccessOnTest extends ValidatorDtdAccessAbstractTest {
+
+    /**
+     * Tests that external DTD call is executed for StringSource by expecting 
an UnkonwHostException.
+     */
+    @Test
+    public void testInvalidMessageWithExternalDTDStringSource() throws 
Exception {
+        unknownHostExceptionEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+
+        template.sendBody("direct:start", ssrfPayloud);
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, 
unknownHostExceptionEndpoint, finallyEndpoint);
+    }
+
+    /**
+     * Tests that external DTD call is executed for StreamSourceby expecting 
an UnknownHostException.
+     */
+    @Test
+    public void testInvalidMessageWithExternalDTDStreamSource() throws 
Exception {
+        unknownHostExceptionEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+        InputStream is = new 
ByteArrayInputStream(ssrfPayloud.getBytes(StandardCharsets.UTF_8));
+        template.sendBody("direct:start", is);
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, 
unknownHostExceptionEndpoint, finallyEndpoint);
+    }
+
+    /**
+     * Tests that XXE is possible for StreamSource by expecting an 
UnkonwHostException.
+     */
+    @Test
+    public void testInvalidMessageXXESourceStream() throws Exception {
+        unknownHostExceptionEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+        InputStream is = new 
ByteArrayInputStream(xxePayloud.getBytes(StandardCharsets.UTF_8));
+        template.sendBody("direct:start", is);
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, 
unknownHostExceptionEndpoint, finallyEndpoint);
+    }
+
+    @Override
+    protected boolean accessExternalDTD() {
+        return true;
+    }
+}
diff --git 
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorEndpointClearCachedSchemaTest.java
 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorEndpointClearCachedSchemaTest.java
new file mode 100644
index 00000000000..d1a86703744
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorEndpointClearCachedSchemaTest.java
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.engine.DefaultResourceLoader;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.apache.camel.urlhandler.pd.Handler;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+/**
+ * Tests whether the ValidatorEndpoint.clearCachedSchema() can be executed 
when several sender threads are running.
+ */
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                ValidatorEndpointClearCachedSchemaTest.class
+        }
+)
+public class ValidatorEndpointClearCachedSchemaTest extends ContextTestSupport 
{
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(ValidatorEndpointClearCachedSchemaTest.class);
+
+    @Test
+    public void testClearCachedSchema() throws Exception {
+
+        MockEndpoint mock = context.getEndpoint("mock:result", 
MockEndpoint.class);
+
+        // send with 5 sender threads in parallel and call clear cache in
+        // between
+        ExecutorService senderPool = Executors.newFixedThreadPool(5);
+        ExecutorService executorClearCache = Executors.newFixedThreadPool(1);
+        for (int i = 0; i < 5; i++) {
+            senderPool.execute(new Sender());
+            if (i == 2) {
+                /*
+                 * The clear cache thread calls xsdEndpoint.clearCachedSchema
+                 */
+                executorClearCache.execute(new ClearCache());
+            }
+        }
+
+        senderPool.shutdown();
+        executorClearCache.shutdown();
+
+        senderPool.awaitTermination(4, TimeUnit.SECONDS);
+
+        // expect at least 5 correct sent messages, the messages sent before
+        // the clearCacheSchema method is called will fail with a validation
+        // error and will nor result in an exchange
+        mock.expectedMinimumMessageCount(5);
+        mock.assertIsSatisfied();
+    }
+
+    @Bean
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        
context.getRegistry().bind(DefaultResourceLoader.RESOURCE_LOADER_KEY_PREFIX + 
"pd", new Handler());
+
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                
from("direct:start").to("validator:pd:somefile.xsd").convertBodyTo(String.class).to("log:after")
+                        .to("mock:result");
+
+            }
+        };
+    }
+
+    private class Sender implements Runnable {
+
+        private final String message = "<?xml version=\"1.0\" 
encoding=\"UTF-8\"?>" + //
+                                       "<p:TestMessage 
xmlns:p=\"http://apache.camel.org/test\";>" + //
+                                       
"<MessageContent>MessageContent</MessageContent>" + //
+                                       "</p:TestMessage>";
+
+        private final byte[] messageBytes = 
message.getBytes(StandardCharsets.UTF_8);
+
+        @Override
+        public void run() {
+            // send up to 5 messages
+            for (int j = 0; j < 5; j++) {
+                try {
+                    Thread.sleep(300);
+                } catch (InterruptedException e) {
+                    throw new RuntimeException(e);
+                }
+                template.sendBody("direct:start", messageBytes);
+            }
+        }
+
+    }
+
+    private class ClearCache implements Runnable {
+
+        @Override
+        public void run() {
+            try {
+                // start later after the first sender
+                // threads are running
+                Thread.sleep(200);
+                clearCachedSchema();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+    }
+
+    private void clearCachedSchema() throws Exception {
+        CamelContext context = this.context;
+        if (context == null) {
+            return;
+        }
+        Collection<Endpoint> endpoints = context.getEndpoints();
+        for (Endpoint endpoint : endpoints) {
+            LOG.info("Endpoint URI: " + endpoint.getEndpointUri());
+            if (endpoint.getEndpointUri().startsWith("validator:")) {
+                ValidatorEndpoint xsltEndpoint = (ValidatorEndpoint) endpoint;
+                xsltEndpoint.clearCachedSchema();
+                LOG.info("schema cache cleared");
+            }
+        }
+    }
+
+}
diff --git 
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIllegalImportTest.java
 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIllegalImportTest.java
new file mode 100644
index 00000000000..afc2b3f4b48
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIllegalImportTest.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.annotation.DirtiesContext;
+
+/**
+ *
+ */
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                ValidatorIllegalImportTest.class
+        }
+)
+public class ValidatorIllegalImportTest extends ContextTestSupport {
+
+    private final String broadCastEvent
+            = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" 
+ "<BroadcastMonitor> "
+              + "<updated>2012-03-01T03:46:26</updated>"
+              + "<stationName>P7 Mix</stationName>" + "<Current>" + 
"<startTime>2012-03-01T03:46:26</startTime>"
+              + "<itemId>1000736343:8505553</itemId>"
+              + "<titleId>785173</titleId>" + 
"<itemCode>9004342-0101</itemCode>" + "<itemReference></itemReference>"
+              + "<titleName>Part Of Me</titleName>" + "<artistName>Katy 
Perry</artistName>" + "<albumName></albumName>"
+              + "</Current>" + "<Next>"
+              + "<startTime>2012-03-01T03:50:00</startTime>" + 
"<itemId>1000736343:8505554</itemId>"
+              + "<titleId>780319</titleId>"
+              + "<itemCode>2318050-0101</itemCode>" + 
"<itemReference></itemReference>" + "<titleName>Fine</titleName>"
+              + "<artistName>Whitney Houston</artistName>" + 
"<albumName></albumName>" + "</Next>" + "</BroadcastMonitor>";
+
+    @Test
+    public void testOk() throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                
from("direct:test").to("validator:org/apache/camel/component/validator/BroadcastMonitorFixed.xsd")
+                        .to("mock:result");
+            }
+        });
+
+        MockEndpoint mock = context.getEndpoint("mock:result", 
MockEndpoint.class);
+        mock.expectedMessageCount(1);
+        template.sendBody("direct:test", broadCastEvent);
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    public void testIllegalImport() throws Exception {
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    
from("direct:test").to("validator:org/apache/camel/component/validator/BroadcastMonitor.xsd").to("mock:result");
+                }
+            });
+            fail("Should have thrown exception");
+        } catch (Exception e) {
+            IllegalArgumentException iae = 
assertIsInstanceOf(IllegalArgumentException.class, e.getCause().getCause());
+            assertTrue(iae.getMessage().startsWith(
+                    "Resource: 
org/apache/camel/component/validator/BroadcastMonitor.xsd refers an invalid 
resource without SystemId."));
+        }
+    }
+}
diff --git 
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIncludeEncodingRouteTest.java
 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIncludeEncodingRouteTest.java
new file mode 100644
index 00000000000..91b74016de0
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIncludeEncodingRouteTest.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+/**
+ *
+ */
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                ValidatorIncludeEncodingRouteTest.class
+        }
+)
+public class ValidatorIncludeEncodingRouteTest extends ContextTestSupport {
+
+    protected MockEndpoint validEndpoint;
+    protected MockEndpoint finallyEndpoint;
+    protected MockEndpoint invalidEndpoint;
+
+    @Test
+    public void testValidMessage() throws Exception {
+        validEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+
+        String body = "<t:text xmlns:t=\"org.text\">\n" + "  
<t:sentence>J'aime les cam\u00E9lid\u00E9s</t:sentence>\n"
+                      + "</t:text>";
+
+        template.sendBody("direct:start", body);
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+    }
+
+    @BeforeEach
+    public void setUp() throws Exception {
+        validEndpoint = context.getEndpoint("mock:valid", MockEndpoint.class);
+        invalidEndpoint = context.getEndpoint("mock:invalid", 
MockEndpoint.class);
+        finallyEndpoint = context.getEndpoint("mock:finally", 
MockEndpoint.class);
+
+        validEndpoint.reset();
+        invalidEndpoint.reset();
+        finallyEndpoint.reset();
+    }
+
+    @Bean
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                
from("direct:start").doTry().to("validator:org/apache/camel/component/validator/text.xsd").to("mock:valid")
+                        .doCatch(NumberFormatException.class)
+                        .process(new Processor() {
+                            @Override
+                            public void process(Exchange exchange) throws 
Exception {
+                                System.err.println("helo " + 
exchange.getException());
+                            }
+                        
}).to("mock:invalid").doFinally().to("mock:finally").end();
+            }
+        };
+    }
+
+}
diff --git 
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIncludeRelativeRouteTest.java
 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIncludeRelativeRouteTest.java
new file mode 100644
index 00000000000..929ef1dc31f
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIncludeRelativeRouteTest.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import org.apache.camel.ValidationException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                ValidatorIncludeRelativeRouteTest.class
+        }
+)
+public class ValidatorIncludeRelativeRouteTest extends 
ValidatorIncludeRouteTest {
+
+    @Override
+    @Test
+    public void testValidMessage() throws Exception {
+        validEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+
+        String body
+                = "<p:person user=\"james\" xmlns:p=\"org.person\" 
xmlns:h=\"org.health.check.person\" xmlns:c=\"org.health.check.common\">\n"
+                  + "  <p:firstName>James</p:firstName>\n" + "  
<p:lastName>Strachan</p:lastName>\n"
+                  + "  <p:city>London</p:city>\n" + "  <h:health>\n"
+                  + "      <h:lastCheck>2011-12-23</h:lastCheck>\n" + "      
<h:status>OK</h:status>\n"
+                  + "      <c:commonElement>" + "          <c:element1/>"
+                  + "          <c:element2/>" + "      </c:commonElement>" + " 
 </h:health>\n" + "</p:person>";
+
+        template.sendBody("direct:start", body);
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+    }
+
+    @BeforeEach
+    public void setUp() throws Exception {
+        validEndpoint = context.getEndpoint("mock:valid", MockEndpoint.class);
+        invalidEndpoint = context.getEndpoint("mock:invalid", 
MockEndpoint.class);
+        finallyEndpoint = context.getEndpoint("mock:finally", 
MockEndpoint.class);
+
+        validEndpoint.reset();
+        invalidEndpoint.reset();
+        finallyEndpoint.reset();
+    }
+
+    @Bean
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                
from("direct:start").doTry().to("validator:org/apache/camel/component/validator/xsds/person.xsd")
+                        .to("mock:valid").doCatch(ValidationException.class)
+                        
.to("mock:invalid").doFinally().to("mock:finally").end();
+            }
+        };
+    }
+
+}
diff --git 
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIncludeRouteTest.java
 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIncludeRouteTest.java
new file mode 100644
index 00000000000..e553c5ad087
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorIncludeRouteTest.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import org.apache.camel.ValidationException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+/**
+ *
+ */
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                ValidatorIncludeRouteTest.class
+        }
+)
+public class ValidatorIncludeRouteTest extends ContextTestSupport {
+
+    protected MockEndpoint validEndpoint;
+    protected MockEndpoint finallyEndpoint;
+    protected MockEndpoint invalidEndpoint;
+
+    @Test
+    public void testValidMessage() throws Exception {
+        validEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+
+        String body = "<p:person user=\"james\" xmlns:p=\"org.person\" 
xmlns:h=\"org.health.check.person\">\n"
+                      + "  <p:firstName>James</p:firstName>\n"
+                      + "  <p:lastName>Strachan</p:lastName>\n" + "  
<p:city>London</p:city>\n" + "  <h:health>\n"
+                      + "      <h:lastCheck>2011-12-23</h:lastCheck>\n"
+                      + "      <h:status>OK</h:status>\n" + "  </h:health>\n" 
+ "</p:person>";
+
+        template.sendBody("direct:start", body);
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+    }
+
+    @Test
+    public void testValidMessageNoHealth() throws Exception {
+        validEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+
+        String body = "<p:person user=\"hiram\"  xmlns:p=\"org.person\" 
xmlns:h=\"org.health.check.person\">\n"
+                      + "  <p:firstName>Hiram</p:firstName>\n"
+                      + "  <p:lastName>Chirino</p:lastName>\n" + "  
<p:city>Tampa</p:city>\n" + "</p:person>";
+
+        template.sendBody("direct:start", body);
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+    }
+
+    @Test
+    public void testValidMessageNoHealthNoNamespace() throws Exception {
+        validEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+
+        String body = "<p:person user=\"hiram\"  xmlns:p=\"org.person\">\n" + 
"  <p:firstName>Hiram</p:firstName>\n"
+                      + "  <p:lastName>Chirino</p:lastName>\n"
+                      + "  <p:city>Tampa</p:city>\n" + "</p:person>";
+
+        template.sendBody("direct:start", body);
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+    }
+
+    @Test
+    public void testInvalidMessage() throws Exception {
+        invalidEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+
+        String body = "<p:person user=\"james\" xmlns:p=\"org.person\" 
xmlns:h=\"org.health.check.person\">\n"
+                      + "  <p:firstName>James</p:firstName>\n"
+                      + "  <p:lastName>Strachan</p:lastName>\n" + "  
<p:city>London</p:city>\n" + "  <h:health>\n"
+                      + "      <h:lastCheck>2011-12-23</h:lastCheck>\n"
+                      + "  </h:health>\n" + "</p:person>";
+
+        template.sendBody("direct:start", body);
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+    }
+
+    @Test
+    public void testInvalidMessageNoHealth() throws Exception {
+        invalidEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+
+        String body = "<p:person user=\"james\" xmlns:p=\"org.person\" 
xmlns:h=\"org.health.check.person\">\n"
+                      + "  <p:firstName>James</p:firstName>\n"
+                      + "  <p:lastName>Strachan</p:lastName>\n" + 
"</p:person>";
+
+        template.sendBody("direct:start", body);
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+    }
+
+    @Test
+    public void testInvalidMessageNoHealthNoNamespace() throws Exception {
+        invalidEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+
+        String body = "<p:person user=\"james\" xmlns:p=\"org.person\">\n" + " 
 <p:firstName>James</p:firstName>\n"
+                      + "  <p:lastName>Strachan</p:lastName>\n" + 
"</p:person>";
+
+        template.sendBody("direct:start", body);
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+    }
+
+    @BeforeEach
+    public void setUp() throws Exception {
+        validEndpoint = context.getEndpoint("mock:valid", MockEndpoint.class);
+        invalidEndpoint = context.getEndpoint("mock:invalid", 
MockEndpoint.class);
+        finallyEndpoint = context.getEndpoint("mock:finally", 
MockEndpoint.class);
+
+        validEndpoint.reset();
+        invalidEndpoint.reset();
+        finallyEndpoint.reset();
+    }
+
+    @Bean
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                
from("direct:start").doTry().to("validator:org/apache/camel/component/validator/person.xsd").to("mock:valid")
+                        .doCatch(ValidationException.class).to("mock:invalid")
+                        .doFinally().to("mock:finally").end();
+            }
+        };
+    }
+
+}
diff --git 
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorLazyStartProducerTest.java
 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorLazyStartProducerTest.java
new file mode 100644
index 00000000000..1d564c36310
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorLazyStartProducerTest.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import java.io.FileNotFoundException;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                ValidatorLazyStartProducerTest.class
+        }
+)
+public class ValidatorLazyStartProducerTest extends ContextTestSupport {
+
+    @Test
+    public void testLazyStartProducerFail() throws Exception {
+        MockEndpoint mock = context.getEndpoint("mock:result", 
MockEndpoint.class);
+        mock.reset();
+        mock.expectedMessageCount(0);
+
+        try {
+            template.sendBody("direct:fail",
+                    "<mail 
xmlns='http://foo.com/bar'><subject>Hey</subject><body>Hello 
world!</body></mail>");
+            fail("Should throw exception");
+        } catch (Exception e) {
+            assertIsInstanceOf(FileNotFoundException.class, e.getCause());
+        }
+
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    public void testLazyStartProducerOk() throws Exception {
+        MockEndpoint mock = context.getEndpoint("mock:result", 
MockEndpoint.class);
+        mock.reset();
+        mock.expectedMessageCount(1);
+
+        template.sendBody("direct:ok",
+                "<mail 
xmlns='http://foo.com/bar'><subject>Hey</subject><body>Hello 
world!</body></mail>");
+
+        mock.assertIsSatisfied();
+    }
+
+    @Bean
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                
from("direct:fail").to("validator:org/apache/camel/component/validator/unknown.xsd?lazyStartProducer=true")
+                        .to("mock:result");
+
+                
from("direct:ok").to("validator:org/apache/camel/component/validator/schema.xsd?lazyStartProducer=true")
+                        .to("mock:result");
+            }
+        };
+    }
+}
diff --git 
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorResourceResolverFactoryTest.java
 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorResourceResolverFactoryTest.java
new file mode 100644
index 00000000000..b8286647b09
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorResourceResolverFactoryTest.java
@@ -0,0 +1,223 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+import org.w3c.dom.ls.LSInput;
+import org.w3c.dom.ls.LSResourceResolver;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.model.language.ConstantExpression;
+import org.apache.camel.model.language.SimpleExpression;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import static org.awaitility.Awaitility.await;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                ValidatorResourceResolverFactoryTest.class
+        }
+)
+public class ValidatorResourceResolverFactoryTest extends ContextTestSupport {
+
+    private static Context jndiContext;
+
+    @Test
+    public void testConfigurationOnEndpoint() throws Exception {
+        // ensure that validator from test method 
"testConfigurationOnComponent"
+        // is unbind
+        jndiContext.unbind("validator");
+
+        String directStart = "direct:start";
+        String endpointUri
+                = 
"validator:org/apache/camel/component/validator/xsds/person.xsd?resourceResolverFactory=#resourceResolverFactory";
+
+        execute(directStart, endpointUri);
+    }
+
+    @Test
+    public void testConfigurationOnComponent() throws Exception {
+        // set resource resolver factory on component
+        ValidatorComponent validatorComponent = new ValidatorComponent();
+        validatorComponent.setResourceResolverFactory(new 
ResourceResolverFactoryImpl());
+        jndiContext.bind("validator", validatorComponent);
+
+        String directStart = "direct:startComponent";
+        String endpointUri = 
"customValidator:org/apache/camel/component/validator/xsds/person.xsd";
+        execute(directStart, endpointUri);
+
+    }
+
+    @Bean
+    public ValidatorComponent customValidator() {
+        ValidatorComponent validatorComponent = new ValidatorComponent();
+        validatorComponent.setResourceResolverFactory(new 
ResourceResolverFactoryImpl());
+
+        return validatorComponent;
+    }
+
+    void execute(String directStart, String endpointUri) throws 
InterruptedException {
+        MockEndpoint endEndpoint = context.getEndpoint("mock:end", 
MockEndpoint.class);
+        endEndpoint.reset();
+        endEndpoint.expectedMessageCount(1);
+
+        final String body
+                = "<p:person user=\"james\" xmlns:p=\"org.person\" 
xmlns:h=\"org.health.check.person\" xmlns:c=\"org.health.check.common\">\n" //
+                  + "  <p:firstName>James</p:firstName>\n" //
+                  + "  <p:lastName>Strachan</p:lastName>\n" //
+                  + "  <p:city>London</p:city>\n" //
+                  + "  <h:health>\n"//
+                  + "      <h:lastCheck>2011-12-23</h:lastCheck>\n" //
+                  + "      <h:status>OK</h:status>\n" //
+                  + "      <c:commonElement>" //
+                  + "          <c:element1/>" //
+                  + "          <c:element2/>" //
+                  + "      </c:commonElement>" //
+                  + "  </h:health>\n" //
+                  + "</p:person>";
+
+        template.sendBody(directStart, body);
+
+        // wait until endpoint is resolved
+        await().atMost(1, TimeUnit.SECONDS).until(() -> 
context.getEndpoint(endpointUri, ValidatorEndpoint.class) != null);
+
+        MockEndpoint.assertIsSatisfied(endEndpoint);
+
+        ValidatorEndpoint validatorEndpoint = context.getEndpoint(endpointUri, 
ValidatorEndpoint.class);
+        assertNotNull(validatorEndpoint);
+        CustomResourceResolver resolver = (CustomResourceResolver) 
validatorEndpoint.getResourceResolver();
+
+        Set<String> uris = resolver.getResolvedResourceUris();
+        checkResourceUri(uris, "../type2.xsd");
+        checkResourceUri(uris, "health/health.xsd");
+        checkResourceUri(uris, "type1.xsd");
+        checkResourceUri(uris, "common/common.xsd");
+    }
+
+    void checkResourceUri(Set<String> uris, String resourceUri) {
+        assertTrue(uris.contains(resourceUri), "Missing resource uri " + 
resourceUri + " in resolved resource URI set");
+    }
+
+//    @Override
+//    protected Registry createRegistry() throws Exception {
+//        jndiContext = createJndiContext();
+//        jndiContext.bind("resourceResolverFactory", new 
ResourceResolverFactoryImpl());
+//        return new DefaultRegistry(new JndiBeanRepository(jndiContext));
+//
+//    }
+
+    public static Context createInitialContext() throws Exception {
+        try (InputStream in = 
ValidatorResourceResolverFactoryTest.class.getClassLoader().getResourceAsStream("jndi-example.properties");)
 {
+            assertNotNull(in, "Cannot find jndi-example.properties on the 
classpath!");
+            Properties properties = new Properties();
+            properties.load(in);
+            return new InitialContext(new Hashtable<>(properties));
+        }
+    }
+
+    @Bean
+    public ResourceResolverFactoryImpl resourceResolverFactory() {
+        return new ResourceResolverFactoryImpl();
+    }
+
+    @BeforeAll
+    public static void beforeAll() throws Exception {
+        jndiContext = createInitialContext();
+        jndiContext.bind("resourceResolverFactory", new 
ResourceResolverFactoryImpl());
+    }
+
+    @Bean
+    protected RouteBuilder routeBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                        .setHeader("xsd_file", new 
ConstantExpression("org/apache/camel/component/validator/xsds/person.xsd"))
+                        .recipientList(new SimpleExpression(
+                                
"validator:${header.xsd_file}?resourceResolverFactory=#resourceResolverFactory"))
+                        .to("mock:end");
+            }
+        };
+    }
+
+    @Bean
+    protected RouteBuilder routeBuilderComponent() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:startComponent")
+                        .setHeader("xsd_file", new 
ConstantExpression("org/apache/camel/component/validator/xsds/person.xsd"))
+                        .recipientList(new 
SimpleExpression("customValidator:${header.xsd_file}")).to("mock:end");
+            }
+        };
+    }
+
+    static class ResourceResolverFactoryImpl implements 
ValidatorResourceResolverFactory {
+
+        @Override
+        public LSResourceResolver createResourceResolver(CamelContext 
camelContext, String rootResourceUri) {
+            return new CustomResourceResolver(camelContext, rootResourceUri);
+        }
+
+    }
+
+    /** Custom resource resolver which collects all resolved resource URIs. */
+    static class CustomResourceResolver extends DefaultLSResourceResolver {
+
+        private final Set<String> resolvedRsourceUris = new HashSet<>();
+
+        CustomResourceResolver(CamelContext camelContext, String resourceUri) {
+            super(camelContext, resourceUri);
+        }
+
+        public Set<String> getResolvedResourceUris() {
+            return resolvedRsourceUris;
+        }
+
+        @Override
+        public LSInput resolveResource(String type, String namespaceURI, 
String publicId, String systemId, String baseURI) {
+            LSInput result = super.resolveResource(type, namespaceURI, 
publicId, systemId, baseURI);
+            resolvedRsourceUris.add(systemId);
+            return result;
+        }
+
+    }
+
+}
diff --git 
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorRootPathTest.java
 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorRootPathTest.java
new file mode 100644
index 00000000000..d867e60bd73
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorRootPathTest.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                ValidatorRootPathTest.class
+        }
+)
+public class ValidatorRootPathTest extends ContextTestSupport {
+
+    protected MockEndpoint validEndpoint;
+    protected MockEndpoint invalidEndpoint;
+
+    @Test
+    public void testRootPath() throws Exception {
+        validEndpoint.expectedMessageCount(1);
+        invalidEndpoint.expectedMessageCount(0);
+
+        template
+                .sendBody("direct:rootPath",
+                        "<report xmlns='http://foo.com/report' 
xmlns:rb='http://foo.com/report-base'><author><rb:name>Knuth</rb:name></author><content><rb:chapter><rb:subject></rb:subject>"
+                                             + 
"<rb:abstract></rb:abstract><rb:body></rb:body></rb:chapter></content></report>");
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint);
+    }
+
+    @BeforeEach
+    public void setUp() throws Exception {
+        validEndpoint = context.getEndpoint("mock:valid", MockEndpoint.class);
+        invalidEndpoint = context.getEndpoint("mock:invalid", 
MockEndpoint.class);
+
+        validEndpoint.reset();
+        invalidEndpoint.reset();
+    }
+
+    @Bean
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                
from("direct:rootPath").to("validator:report.xsd").to("mock:valid");
+            }
+        };
+    }
+
+}
diff --git 
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorRouteTest.java
 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorRouteTest.java
new file mode 100644
index 00000000000..9f54a605493
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorRouteTest.java
@@ -0,0 +1,236 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.ValidationException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import 
org.apache.camel.support.processor.validation.NoXmlHeaderValidationException;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                ValidatorRouteTest.class
+        }
+)
+public class ValidatorRouteTest extends ContextTestSupport {
+
+    @Autowired
+    private ProducerTemplate template;
+
+    @Autowired
+    private CamelContext context;
+
+    @Test
+    public void testValidMessage() throws Exception {
+        validEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+
+        template.sendBody("direct:start",
+                "<mail 
xmlns='http://foo.com/bar'><subject>Hey</subject><body>Hello 
world!</body></mail>");
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+    }
+
+    @Test
+    public void testValidMessageInHeader() throws Exception {
+        validEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+
+        template.sendBodyAndHeader("direct:startHeaders", null, 
"headerToValidate",
+                "<mail 
xmlns='http://foo.com/bar'><subject>Hey</subject><body>Hello 
world!</body></mail>");
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+    }
+
+    @Test
+    public void testInvalidMessage() throws Exception {
+        invalidEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+
+        template.sendBody("direct:start", "<mail 
xmlns='http://foo.com/bar'><body>Hello world!</body></mail>");
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+    }
+
+    @Test
+    public void testInvalidMessageInHeader() throws Exception {
+        invalidEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+
+        template.sendBodyAndHeader("direct:startHeaders", null, 
"headerToValidate",
+                "<mail xmlns='http://foo.com/bar'><body>Hello 
world!</body></mail>");
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+    }
+
+    @Test
+    public void testNullHeaderNoFail() throws Exception {
+        validEndpoint.expectedMessageCount(1);
+
+        template.sendBodyAndHeader("direct:startNullHeaderNoFail", null, 
"headerToValidate", null);
+
+        MockEndpoint.assertIsSatisfied(validEndpoint);
+    }
+
+    @Test
+    public void testNullHeader() throws Exception {
+        validEndpoint.setExpectedMessageCount(0);
+
+        Exchange in = 
context.getEndpoint("direct:startNoHeaderException").createExchange(ExchangePattern.InOut);
+
+        in.getIn().setBody(null);
+        in.getIn().setHeader("headerToValidate", null);
+
+        Exchange out = template.send("direct:startNoHeaderException", in);
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+
+        Exception exception = out.getException();
+        assertTrue(out.isFailed(), "Should be failed");
+        boolean b = exception instanceof NoXmlHeaderValidationException;
+        assertTrue(b, "Exception should be correct type");
+        assertTrue(exception.getMessage().contains("headerToValidate"), 
"Exception should mention missing header");
+    }
+
+    @Test
+    public void testInvalideBytesMessage() throws Exception {
+        invalidEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+
+        template.sendBody("direct:start", "<mail 
xmlns='http://foo.com/bar'><body>Hello world!</body></mail>".getBytes());
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+    }
+
+    @Test
+    public void testInvalidBytesMessageInHeader() throws Exception {
+        invalidEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+
+        template.sendBodyAndHeader("direct:startHeaders", null, 
"headerToValidate",
+                "<mail xmlns='http://foo.com/bar'><body>Hello 
world!</body></mail>".getBytes());
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+    }
+
+    @Test
+    public void testUseNotASharedSchema() throws Exception {
+        validEndpoint.expectedMessageCount(1);
+
+        template.sendBody("direct:useNotASharedSchema",
+                "<mail 
xmlns='http://foo.com/bar'><subject>Hey</subject><body>Hello 
world!</body></mail>");
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+    }
+
+    @Test
+    public void testConcurrentUseNotASharedSchema() throws Exception {
+        validEndpoint.expectedMessageCount(10);
+        // latch for the 10 exchanges we expect
+        final CountDownLatch latch = new CountDownLatch(10);
+        // setup a task executor to be able send the messages in parallel
+        ExecutorService executor = Executors.newCachedThreadPool();
+        for (int i = 0; i < 10; i++) {
+            executor.execute(new Runnable() {
+                public void run() {
+                    template.requestBody("direct:useNotASharedSchema",
+                            "<mail 
xmlns='http://foo.com/bar'><subject>Hey</subject><body>Hello 
world!</body></mail>");
+                    latch.countDown();
+                }
+            });
+        }
+
+        try {
+            // wait for test completion, timeout after 30 sec to let other unit
+            // test run to not wait forever
+            assertTrue(latch.await(30000L, TimeUnit.MILLISECONDS));
+            assertEquals(0, latch.getCount(), "Latch should be zero");
+        } finally {
+            executor.shutdown();
+        }
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+    }
+
+    @BeforeEach
+    public void setUp() throws Exception {
+        validEndpoint = context.getEndpoint("mock:valid", MockEndpoint.class);
+        invalidEndpoint = context.getEndpoint("mock:invalid", 
MockEndpoint.class);
+        finallyEndpoint = context.getEndpoint("mock:finally", 
MockEndpoint.class);
+    }
+
+    @AfterEach
+    public void reset() {
+        validEndpoint.reset();
+        invalidEndpoint.reset();
+        finallyEndpoint.reset();
+    }
+
+    @Bean
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                
from("direct:start").doTry().to("validator:org/apache/camel/component/validator/schema.xsd").to("mock:valid")
+                        .doCatch(ValidationException.class).to("mock:invalid")
+                        .doFinally().to("mock:finally").end();
+
+                from("direct:startHeaders").doTry()
+                        
.to("validator:org/apache/camel/component/validator/schema.xsd?headerName=headerToValidate")
+                        .to("mock:valid")
+                        
.doCatch(ValidationException.class).to("mock:invalid").doFinally().to("mock:finally").end();
+
+                from("direct:startNoHeaderException")
+                        
.to("validator:org/apache/camel/component/validator/schema.xsd?headerName=headerToValidate")
+                        .to("mock:valid");
+
+                from("direct:startNullHeaderNoFail").to(
+                        
"validator:org/apache/camel/component/validator/schema.xsd?headerName=headerToValidate&failOnNullHeader=false")
+                        .to("mock:valid");
+
+                from("direct:useNotASharedSchema")
+                        
.to("validator:org/apache/camel/component/validator/schema.xsd?useSharedSchema=false").to("mock:valid");
+            }
+        };
+    }
+
+}
diff --git 
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorWithResourceResolverRouteTest.java
 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorWithResourceResolverRouteTest.java
new file mode 100644
index 00000000000..fc3654cd2ce
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/component/validator/ValidatorWithResourceResolverRouteTest.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.validator;
+
+import java.net.URL;
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+import org.w3c.dom.ls.LSResourceResolver;
+
+import org.apache.camel.ValidationException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.processor.validation.CatalogLSResourceResolver;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.support.ResourceHelper;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.apache.xml.resolver.CatalogManager;
+import org.apache.xml.resolver.tools.CatalogResolver;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                ValidatorWithResourceResolverRouteTest.class
+        }
+)
+public class ValidatorWithResourceResolverRouteTest extends ContextTestSupport 
{
+
+    protected MockEndpoint validEndpoint;
+    protected MockEndpoint finallyEndpoint;
+    protected MockEndpoint invalidEndpoint;
+
+    @Test
+    public void testValidMessage() throws Exception {
+        validEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+        invalidEndpoint.expectedMessageCount(0);
+        template
+                .sendBody("direct:start",
+                        "<report xmlns='http://foo.com/report' 
xmlns:rb='http://foo.com/report-base'><author><rb:name>Knuth</rb:name></author><content><rb:chapter><rb:subject></rb:subject>"
+                                          + 
"<rb:abstract></rb:abstract><rb:body></rb:body></rb:chapter></content></report>");
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+    }
+
+    @Test
+    public void testInvalidMessage() throws Exception {
+        validEndpoint.expectedMessageCount(0);
+        invalidEndpoint.expectedMessageCount(1);
+        finallyEndpoint.expectedMessageCount(1);
+
+        template.sendBody("direct:start",
+                "<report xmlns='http://foo.com/report' 
xmlns:rb='http://foo.com/report-base'><author><rb:name>Knuth</rb:name></author></report>");
+
+        MockEndpoint.assertIsSatisfied(validEndpoint, invalidEndpoint, 
finallyEndpoint);
+    }
+
+    @BeforeEach
+    public void setUp() throws Exception {
+        validEndpoint = context.getEndpoint("mock:valid", MockEndpoint.class);
+        invalidEndpoint = context.getEndpoint("mock:invalid", 
MockEndpoint.class);
+        finallyEndpoint = context.getEndpoint("mock:finally", 
MockEndpoint.class);
+
+        validEndpoint.reset();
+        invalidEndpoint.reset();
+        finallyEndpoint.reset();
+    }
+
+    @Bean
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        // we have to do it here, because we need the context created first
+        CatalogManager.getStaticManager().setIgnoreMissingProperties(true);
+        CatalogResolver catalogResolver = new CatalogResolver(true);
+        URL catalogUrl = ResourceHelper.resolveMandatoryResourceAsUrl(context,
+                "org/apache/camel/component/validator/catalog.cat");
+        catalogResolver.getCatalog().parseCatalog(catalogUrl);
+        LSResourceResolver resourceResolver = new 
CatalogLSResourceResolver(catalogResolver);
+        context.getRegistry().bind("resourceResolver", resourceResolver);
+
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start").doTry()
+                        
.to("validator:org/apache/camel/component/validator/report.xsd?resourceResolver=#resourceResolver")
+                        .to("mock:valid")
+                        
.doCatch(ValidationException.class).to("mock:invalid").doFinally().to("mock:finally").end();
+            }
+        };
+    }
+}
diff --git 
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/processor/validation/CatalogLSResourceResolver.java
 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/processor/validation/CatalogLSResourceResolver.java
new file mode 100644
index 00000000000..a4edce20c37
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/processor/validation/CatalogLSResourceResolver.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.processor.validation;
+
+import java.io.InputStream;
+import java.io.Reader;
+
+import org.w3c.dom.ls.LSInput;
+import org.w3c.dom.ls.LSResourceResolver;
+
+import org.xml.sax.InputSource;
+
+import org.apache.xml.resolver.tools.CatalogResolver;
+
+public class CatalogLSResourceResolver implements LSResourceResolver {
+
+       CatalogResolver catalogResolver;
+
+       public CatalogLSResourceResolver() {
+       }
+
+       public CatalogLSResourceResolver(CatalogResolver catalogResolver) {
+               this.catalogResolver = catalogResolver;
+       }
+
+       public CatalogResolver getCatalogResolver() {
+               return catalogResolver;
+       }
+
+       public void setCatalogResolver(CatalogResolver catalogResolver) {
+               this.catalogResolver = catalogResolver;
+       }
+
+       @Override
+       public LSInput resolveResource(String type, String namespaceURI, String 
publicId, String systemId, String baseURI) {
+               return new LSInputSource(namespaceURI, publicId, systemId, 
baseURI);
+       }
+
+       class LSInputSource implements LSInput {
+               private InputSource inputSource;
+               private String publicId;
+               private String systemId;
+               private String baseURI;
+
+               LSInputSource(String namespaceURI, String publicId, String 
systemId, String baseURI) {
+                       if (publicId == null) {
+                               publicId = namespaceURI;
+                       }
+
+                       this.publicId = publicId;
+                       this.systemId = systemId;
+                       this.baseURI = baseURI;
+
+                       if (catalogResolver == null) {
+                               throw new 
IllegalStateException("catalogResolver must be provided");
+                       }
+
+                       this.inputSource = 
catalogResolver.resolveEntity(publicId, systemId);
+               }
+
+               @Override
+               public Reader getCharacterStream() {
+                       return null;
+               }
+
+               @Override
+               public void setCharacterStream(Reader characterStream) {
+                       // noop
+               }
+
+               @Override
+               public InputStream getByteStream() {
+                       return inputSource != null ? 
inputSource.getByteStream() : null;
+               }
+
+               @Override
+               public void setByteStream(InputStream byteStream) {
+                       if (inputSource != null) {
+                               inputSource.setByteStream(byteStream);
+                       }
+               }
+
+               @Override
+               public String getStringData() {
+                       return null;
+               }
+
+               @Override
+               public void setStringData(String stringData) {
+                       // noop
+               }
+
+               @Override
+               public String getSystemId() {
+                       if (inputSource != null) {
+                               return inputSource.getSystemId();
+                       }
+
+                       return systemId;
+               }
+
+               @Override
+               public void setSystemId(String systemId) {
+                       if (inputSource != null) {
+                               inputSource.setSystemId(systemId);
+                       }
+               }
+
+               @Override
+               public String getPublicId() {
+                       if (inputSource != null) {
+                               return inputSource.getPublicId();
+                       }
+
+                       return publicId;
+               }
+
+               @Override
+               public void setPublicId(String publicId) {
+                       if (inputSource != null) {
+                               inputSource.setPublicId(publicId);
+                       } else {
+                               this.publicId = publicId;
+                       }
+               }
+
+               @Override
+               public String getBaseURI() {
+                       return baseURI;
+               }
+
+               @Override
+               public void setBaseURI(String baseURI) {
+                       // noop
+               }
+
+               @Override
+               public String getEncoding() {
+                       if (inputSource != null) {
+                               return inputSource.getEncoding();
+                       }
+
+                       return null;
+               }
+
+               @Override
+               public void setEncoding(String encoding) {
+                       if (inputSource != null) {
+                               inputSource.setEncoding(encoding);
+                       }
+               }
+
+               @Override
+               public boolean getCertifiedText() {
+                       return true;
+               }
+
+               @Override
+               public void setCertifiedText(boolean certifiedText) {
+                       // noop
+               }
+       }
+}
diff --git 
a/components-starter/camel-validator-starter/src/test/java/org/apache/camel/urlhandler/pd/Handler.java
 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/urlhandler/pd/Handler.java
new file mode 100644
index 00000000000..6ab9168970c
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/java/org/apache/camel/urlhandler/pd/Handler.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.urlhandler.pd;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.camel.spi.Resource;
+import org.apache.camel.support.ResourceResolverSupport;
+import org.apache.camel.support.ResourceSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class to simulate a change of the XSD document. During the first call of 
the resource a XSD is returned which does
+ * not fit to the XML document. In the second call a XSD fitting to the XML 
document is returned. Used in
+ * org.apache.camel.component.validator.ValidatorEndpointClearCachedSchemaTest
+ */
+public class Handler extends ResourceResolverSupport {
+       private static final Logger LOG = 
LoggerFactory.getLogger(Handler.class);
+
+       // wrong  element name will cause the validation to fail
+       private static final String XSD_TEMPLATE_1 = "<?xml version=\"1.0\" 
encoding=\"UTF-8\"?>\n" +
+                       "<xsd:schema 
targetNamespace=\"http://apache.camel.org/test\"; " +
+                       "            xmlns=\"http://apache.camel.org/test\"; " +
+                       "            
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\";>" +
+                       "    <xsd:complexType name=\"TestMessage\">" +
+                       "        <xsd:sequence>" +
+                       "            <xsd:element name=\"Content\" 
type=\"xsd:string\" />" +
+                       "        </xsd:sequence>" +
+                       "        <xsd:attribute name=\"attr\" 
type=\"xsd:string\" default=\"xsd1\"/>" +
+                       "    </xsd:complexType>" +
+                       "    <xsd:element name=\"TestMessage\" 
type=\"TestMessage\" />" +
+                       "</xsd:schema>";
+
+       // correct element name, the validation will be corerct
+       private static final String XSD_TEMPLATE_2 = 
XSD_TEMPLATE_1.replace("\"Content\"", "\"MessageContent\"");
+
+       private final AtomicInteger counter;
+
+       public Handler() {
+               super("pd");
+
+               this.counter = new AtomicInteger();
+       }
+
+       @Override
+       protected Resource createResource(String location, String remaining) {
+               return new ResourceSupport("mem", location) {
+                       @Override
+                       public boolean exists() {
+                               return true;
+                       }
+
+                       @Override
+                       public InputStream getInputStream() throws IOException {
+                               if (counter.getAndIncrement() == 0) {
+                                       LOG.info("resolved XSD1");
+                                       return new 
ByteArrayInputStream(XSD_TEMPLATE_1.getBytes(StandardCharsets.UTF_8));
+                               } else {
+                                       LOG.info("resolved XSD2");
+
+                                       return new 
ByteArrayInputStream(XSD_TEMPLATE_2.getBytes(StandardCharsets.UTF_8));
+                               }
+                       }
+               };
+       }
+}
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/jndi-example.properties
 
b/components-starter/camel-validator-starter/src/test/resources/jndi-example.properties
new file mode 100644
index 00000000000..3807dfc1e3d
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/jndi-example.properties
@@ -0,0 +1,24 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+# START SNIPPET: jndi
+
+java.naming.factory.initial = 
org.apache.camel.support.jndi.CamelInitialContextFactory
+
+# the following properties will be copied into the context
+foo = bar
+
+# END SNIPPET: jndi
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/BroadcastMonitor.xsd
 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/BroadcastMonitor.xsd
new file mode 100755
index 00000000000..a88a315bab7
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/BroadcastMonitor.xsd
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"; 
elementFormDefault="qualified">
+       <xs:import namespace="http://www.w3.org/XML/1998/namespace"; />
+       <xs:element name="BroadcastMonitor">
+               <xs:complexType>
+                       <xs:sequence>
+                       <xs:element name="updated" type="xs:dateTime" 
maxOccurs="1" minOccurs="0"></xs:element>
+                       <xs:element name="stationName" type="xs:string" 
maxOccurs="1" minOccurs="0"></xs:element>
+                               <xs:element name="Current">
+                                       <xs:complexType>
+                                               <xs:sequence>
+                                               <xs:element name="startTime" 
type="xs:dateTime" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="itemId" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="titleId" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="itemCode" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element 
name="itemReference" type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="titleName" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="artistName" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="albumName" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               </xs:sequence>
+                                       </xs:complexType>
+                               </xs:element>
+                               <xs:element name="Next">
+                                       <xs:complexType>
+                                               <xs:sequence>
+                                               <xs:element name="startTime" 
type="xs:dateTime" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="itemId" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="titleId" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="itemCode" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element 
name="itemReference" type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="titleName" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="artistName" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="albumName" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               </xs:sequence>
+                                       </xs:complexType>
+                               </xs:element>
+                       </xs:sequence>
+               </xs:complexType>
+       </xs:element>
+</xs:schema>
\ No newline at end of file
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/BroadcastMonitorFixed.xsd
 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/BroadcastMonitorFixed.xsd
new file mode 100755
index 00000000000..5f5785faeb5
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/BroadcastMonitorFixed.xsd
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"; 
elementFormDefault="qualified">
+       <xs:element name="BroadcastMonitor">
+               <xs:complexType>
+                       <xs:sequence>
+                       <xs:element name="updated" type="xs:dateTime" 
maxOccurs="1" minOccurs="0"></xs:element>
+                       <xs:element name="stationName" type="xs:string" 
maxOccurs="1" minOccurs="0"></xs:element>
+                               <xs:element name="Current">
+                                       <xs:complexType>
+                                               <xs:sequence>
+                                               <xs:element name="startTime" 
type="xs:dateTime" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="itemId" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="titleId" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="itemCode" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element 
name="itemReference" type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="titleName" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="artistName" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="albumName" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               </xs:sequence>
+                                       </xs:complexType>
+                               </xs:element>
+                               <xs:element name="Next">
+                                       <xs:complexType>
+                                               <xs:sequence>
+                                               <xs:element name="startTime" 
type="xs:dateTime" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="itemId" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="titleId" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="itemCode" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element 
name="itemReference" type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="titleName" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="artistName" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               <xs:element name="albumName" 
type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
+                                               </xs:sequence>
+                                       </xs:complexType>
+                               </xs:element>
+                       </xs:sequence>
+               </xs:complexType>
+       </xs:element>
+</xs:schema>
\ No newline at end of file
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/catalog.cat
 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/catalog.cat
new file mode 100644
index 00000000000..4a86ac6050c
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/catalog.cat
@@ -0,0 +1,2 @@
+PUBLIC "http://foo.com/report"; "report.xsd"
+PUBLIC "http://foo.com/report-base"; "report-base.xsd"
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/health.xsd
 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/health.xsd
new file mode 100644
index 00000000000..c6e29f1599c
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/health.xsd
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema
+        attributeFormDefault="unqualified"
+        elementFormDefault="qualified"
+        targetNamespace="org.health.check.person"
+        xmlns:xs="http://www.w3.org/2001/XMLSchema";>
+    <xs:element name="health" type="org:healthType" 
xmlns:org="org.health.check.person"/>
+    <xs:complexType name="healthType">
+        <xs:sequence>
+            <xs:element type="xs:string" name="lastCheck"/>
+            <xs:element type="xs:string" name="status"/>
+        </xs:sequence>
+    </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/person.xsd
 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/person.xsd
new file mode 100644
index 00000000000..d9256a3b12d
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/person.xsd
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema attributeFormDefault="unqualified"
+           elementFormDefault="qualified"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema";
+           xmlns:p="org.person"
+           targetNamespace="org.person"
+           xmlns:h="org.health.check.person">
+    <xs:import schemaLocation="health.xsd" 
namespace="org.health.check.person"/>
+    <xs:element name="person" type="p:personType">
+</xs:element>
+<xs:complexType name="personType">
+    <xs:sequence>
+        <xs:element type="xs:string" name="firstName"/>
+        <xs:element type="xs:string" name="lastName"/>
+        <xs:element type="xs:string" name="city"/>
+        <xs:element ref="h:health" maxOccurs="1" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute type="xs:string" name="user"/>
+</xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/report-base.xsd
 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/report-base.xsd
new file mode 100644
index 00000000000..d01ca831e67
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/report-base.xsd
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema elementFormDefault="qualified" version="1.0"
+           targetNamespace="http://foo.com/report-base";
+           xmlns:tns="http://foo.com/report-base";
+           xmlns:xs="http://www.w3.org/2001/XMLSchema";>
+
+
+  <xs:element name="content" type="tns:content" />
+  
+  <xs:complexType name="content">
+       <xs:sequence>
+               <xs:element name="chapter" type="tns:chapter" 
maxOccurs="unbounded" />
+       </xs:sequence>
+  </xs:complexType>
+         
+  <xs:complexType name="chapter">
+    <xs:sequence>
+      <xs:element name="subject" type="xs:string"/>
+      <xs:element name="abstract" type="xs:string"/>
+      <xs:element name="body" type="xs:string"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="person">
+    <xs:sequence>
+      <xs:element name="name" type="xs:string"/>
+      <xs:element name="email" type="xs:string" minOccurs="0"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/report.xsd
 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/report.xsd
new file mode 100644
index 00000000000..1ca8c386425
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/report.xsd
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema elementFormDefault="qualified" version="1.0"
+           targetNamespace="http://foo.com/report";
+           xmlns:rb="http://foo.com/report-base";
+           xmlns:xs="http://www.w3.org/2001/XMLSchema";>
+
+  <xs:import namespace="http://foo.com/report-base"; 
schemaLocation="http://foo.com/report-base.xsd"; />
+
+  <xs:element name="report">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element name="author" type="rb:person" maxOccurs="unbounded" />
+               <xs:element name="content" type="rb:content" />
+        <xs:any namespace="##any" processContents="lax" minOccurs="0" 
maxOccurs="unbounded"/>
+      </xs:sequence>
+    </xs:complexType>
+  </xs:element>
+</xs:schema>
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/schema.xsd
 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/schema.xsd
new file mode 100644
index 00000000000..11ea3a6cb15
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/schema.xsd
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema elementFormDefault="qualified" version="1.0"
+           targetNamespace="http://foo.com/bar";
+           xmlns:xs="http://www.w3.org/2001/XMLSchema";>
+
+
+  <xs:element name="mail">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element name="subject" type="xs:string"/>
+        <xs:element name="body" type="xs:string"/>
+      </xs:sequence>
+    </xs:complexType>
+  </xs:element>
+
+</xs:schema>
+
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/sentence.xsd
 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/sentence.xsd
new file mode 100644
index 00000000000..29662697905
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/sentence.xsd
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema attributeFormDefault="unqualified"
+       elementFormDefault="qualified" targetNamespace="org.text.sentence"
+       xmlns:xs="http://www.w3.org/2001/XMLSchema";>
+       <xs:simpleType name="sentence">
+               <xs:restriction base="xs:string">
+                       <xs:pattern value="[a-zA-Z&#233;' ]*" />
+               </xs:restriction>
+       </xs:simpleType>
+</xs:schema>
\ No newline at end of file
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/text.xsd
 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/text.xsd
new file mode 100644
index 00000000000..8cdbb14faad
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/text.xsd
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema attributeFormDefault="unqualified"
+       elementFormDefault="qualified" 
xmlns:xs="http://www.w3.org/2001/XMLSchema";
+       xmlns:p="org.text" targetNamespace="org.text" 
xmlns:s="org.text.sentence">
+       <xs:import schemaLocation="sentence.xsd" namespace="org.text.sentence" 
/>
+       <xs:element name="text" type="p:textType">
+       </xs:element>
+       <xs:complexType name="textType">
+               <xs:sequence>
+                       <xs:element type="s:sentence" name="sentence" 
minOccurs="0"/>
+               </xs:sequence>
+       </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/unsecuredSchema.xsd
 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/unsecuredSchema.xsd
new file mode 100644
index 00000000000..8e21fe5f4f9
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/unsecuredSchema.xsd
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema elementFormDefault="qualified" version="1.0"
+           targetNamespace="http://foo.com/bar";
+           xmlns:xs="http://www.w3.org/2001/XMLSchema";>
+
+  <xs:element name="mail">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element name="subject" type="xs:string"  minOccurs="1" 
maxOccurs="999999999" />
+        <xs:element name="body" type="xs:string"/>
+      </xs:sequence>
+    </xs:complexType>
+  </xs:element>
+
+</xs:schema>
+
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/customer.xsd
 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/customer.xsd
new file mode 100644
index 00000000000..73f4c1775c5
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/customer.xsd
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";>
+       <xs:complexType name="CustomerType">
+               <xs:sequence>
+                       <xs:element name="name" type="CustNameType"/>
+                       <xs:element name="number" type="xs:integer"/>
+               </xs:sequence>
+       </xs:complexType>
+       <xs:simpleType name="CustNameType">
+               <xs:restriction base="xs:string"/>
+       </xs:simpleType>
+</xs:schema>
\ No newline at end of file
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/health/common/common.xsd
 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/health/common/common.xsd
new file mode 100644
index 00000000000..8156d768f8b
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/health/common/common.xsd
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema
+    attributeFormDefault="unqualified"
+    elementFormDefault="qualified"
+    targetNamespace="org.health.check.common"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema";>
+    <xs:element name="commonElement" type="common:commonType" 
xmlns:common="org.health.check.common"/>
+    <xs:complexType name="commonType">
+        <xs:sequence>
+            <xs:element type="xs:string" name="element1"/>
+            <xs:element type="xs:string" name="element2"/>
+        </xs:sequence>
+    </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/health/health.xsd
 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/health/health.xsd
new file mode 100644
index 00000000000..01113757743
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/health/health.xsd
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema
+        attributeFormDefault="unqualified"
+        elementFormDefault="qualified"
+        targetNamespace="org.health.check.person"
+        xmlns:xs="http://www.w3.org/2001/XMLSchema";
+        xmlns:common="org.health.check.common">
+    <xs:import schemaLocation="type1.xsd" namespace="org.health.check.type1" />
+    <xs:import schemaLocation="common/common.xsd" 
namespace="org.health.check.common"/>
+    <xs:element name="health" type="org:healthType" 
xmlns:org="org.health.check.person"/>
+    
+    <xs:complexType name="healthType">
+        <xs:sequence>
+            <xs:element type="xs:string" name="lastCheck"/>
+            <xs:element type="xs:string" name="status"/>
+            <xs:element ref="common:commonElement" maxOccurs="1" 
minOccurs="0"/>
+        </xs:sequence>
+    </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/health/type1.xsd
 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/health/type1.xsd
new file mode 100644
index 00000000000..79e45d8c3b3
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/health/type1.xsd
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema 
+    xmlns:xs="http://www.w3.org/2001/XMLSchema"; 
+    elementFormDefault="qualified"
+    targetNamespace="org.health.check.type1">
+    
+    <xs:import schemaLocation="../type2.xsd" 
namespace="org.health.check.type2"/>
+    <xs:import schemaLocation="common/common.xsd" 
namespace="org.health.check.common"/>
+    
+</xs:schema>
\ No newline at end of file
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/order.xsd
 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/order.xsd
new file mode 100644
index 00000000000..543e608d578
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/order.xsd
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
+               targetNamespace="http://example.org/ord";
+               xmlns="http://example.org/ord";
+               xmlns:prod="http://example.org/prod";>
+       <xs:include 
schemaLocation="https://raw.githubusercontent.com/apache/camel/main/core/camel-core/src/test/resources/org/apache/camel/component/validator/xsds/customer.xsd"/>
+       <xs:import namespace="http://example.org/prod";
+                       
schemaLocation="https://raw.githubusercontent.com/apache/camel/main/core/camel-core/src/test/resources/org/apache/camel/component/validator/xsds/product.xsd"/>
+       <xs:element name="order" type="OrderType"/>
+       <xs:complexType name="OrderType">
+               <xs:sequence>
+                       <xs:element name="customer" type="CustomerType"/>
+                       <xs:element name="items" type="prod:ItemsType"/>
+               </xs:sequence>
+       </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/person.xsd
 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/person.xsd
new file mode 100644
index 00000000000..8f6757b56d9
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/person.xsd
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema attributeFormDefault="unqualified"
+           elementFormDefault="qualified"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema";
+           xmlns:p="org.person"
+           targetNamespace="org.person"
+           xmlns:h="org.health.check.person">
+    <xs:import schemaLocation="health/health.xsd" 
namespace="org.health.check.person"/>
+    <xs:import schemaLocation="health/common/common.xsd" 
namespace="org.health.check.common"/>
+    <xs:import schemaLocation="health/type1.xsd" 
namespace="org.health.check.type1" />
+    <xs:element name="person" type="p:personType">
+</xs:element>
+<xs:complexType name="personType">
+    <xs:sequence>
+        <xs:element type="xs:string" name="firstName"/>
+        <xs:element type="xs:string" name="lastName"/>
+        <xs:element type="xs:string" name="city"/>
+        <xs:element ref="h:health" maxOccurs="1" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute type="xs:string" name="user"/>
+</xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/product.xsd
 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/product.xsd
new file mode 100644
index 00000000000..a9946303f2a
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/product.xsd
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
+               xmlns="http://example.org/prod";
+               targetNamespace="http://example.org/prod";>
+       <xs:complexType name="ItemsType">
+               <xs:sequence>
+                       <xs:element name="product" type="ProductType"/>
+               </xs:sequence>
+       </xs:complexType>
+       <xs:complexType name="ProductType">
+               <xs:sequence>
+                       <xs:element name="number" type="xs:integer"/>
+                       <xs:element name="name" type="xs:string"/>
+                       <xs:element name="size" type="SizeType"/>
+                       <xs:element name="color" type="ColorType"/>
+               </xs:sequence>
+       </xs:complexType>
+       <xs:complexType name="SizeType">
+               <xs:simpleContent>
+                       <xs:extension base="xs:integer">
+                               <xs:attribute name="system" type="xs:string"/>
+                       </xs:extension>
+               </xs:simpleContent>
+       </xs:complexType>
+       <xs:complexType name="ColorType">
+               <xs:attribute name="value" type="xs:string"/>
+       </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/type2.xsd
 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/type2.xsd
new file mode 100644
index 00000000000..f227ac06dff
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/org/apache/camel/component/validator/xsds/type2.xsd
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema 
+    xmlns:xs="http://www.w3.org/2001/XMLSchema"; 
+    elementFormDefault="qualified"
+    targetNamespace="org.health.check.type2">
+    
+</xs:schema>
\ No newline at end of file
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/report-base.xsd 
b/components-starter/camel-validator-starter/src/test/resources/report-base.xsd
new file mode 100644
index 00000000000..d01ca831e67
--- /dev/null
+++ 
b/components-starter/camel-validator-starter/src/test/resources/report-base.xsd
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema elementFormDefault="qualified" version="1.0"
+           targetNamespace="http://foo.com/report-base";
+           xmlns:tns="http://foo.com/report-base";
+           xmlns:xs="http://www.w3.org/2001/XMLSchema";>
+
+
+  <xs:element name="content" type="tns:content" />
+  
+  <xs:complexType name="content">
+       <xs:sequence>
+               <xs:element name="chapter" type="tns:chapter" 
maxOccurs="unbounded" />
+       </xs:sequence>
+  </xs:complexType>
+         
+  <xs:complexType name="chapter">
+    <xs:sequence>
+      <xs:element name="subject" type="xs:string"/>
+      <xs:element name="abstract" type="xs:string"/>
+      <xs:element name="body" type="xs:string"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="person">
+    <xs:sequence>
+      <xs:element name="name" type="xs:string"/>
+      <xs:element name="email" type="xs:string" minOccurs="0"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git 
a/components-starter/camel-validator-starter/src/test/resources/report.xsd 
b/components-starter/camel-validator-starter/src/test/resources/report.xsd
new file mode 100644
index 00000000000..320865ad167
--- /dev/null
+++ b/components-starter/camel-validator-starter/src/test/resources/report.xsd
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xs:schema elementFormDefault="qualified" version="1.0"
+           targetNamespace="http://foo.com/report";
+           xmlns:rb="http://foo.com/report-base";
+           xmlns:xs="http://www.w3.org/2001/XMLSchema";>
+
+  <xs:import namespace="http://foo.com/report-base"; 
schemaLocation="report-base.xsd"/>
+
+  <xs:element name="report">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element name="author" type="rb:person" maxOccurs="unbounded"/>
+        <xs:element name="content" type="rb:content"/>
+        <xs:any namespace="##any" processContents="lax" minOccurs="0" 
maxOccurs="unbounded"/>
+      </xs:sequence>
+    </xs:complexType>
+  </xs:element>
+</xs:schema>
\ No newline at end of file

Reply via email to