You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ff...@apache.org on 2022/03/15 19:25:06 UTC

[camel-spring-boot] branch main updated: [CAMEL-17794]add tests in camel-saxon-starter (#468)

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

ffang 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 8e926a2  [CAMEL-17794]add tests in camel-saxon-starter (#468)
8e926a2 is described below

commit 8e926a2cf299a2ce68be7904089e324366553167
Author: Freeman(Yue) Fang <fr...@gmail.com>
AuthorDate: Tue Mar 15 15:24:56 2022 -0400

    [CAMEL-17794]add tests in camel-saxon-starter (#468)
---
 .../springboot/BeanWithXQueryInjectionTest.java    | 110 ++++++++++
 .../language/xquery/springboot/FromFileBase.java   |  73 +++++++
 .../SaxonLanguageExtensionFunctionsTest.java       |  98 +++++++++
 .../xquery/springboot/SaxonXPathSplitTest.java     | 110 ++++++++++
 .../language/xquery/springboot/SaxonXPathTest.java | 104 ++++++++++
 .../xquery/springboot/SoapPayloadBean.java         |  35 ++++
 .../xquery/springboot/SoapPayloadBeanTest.java     |  83 ++++++++
 .../XPathHeaderEnableSaxonJavaDslTest.java         | 119 +++++++++++
 .../XPathSplitChoicePerformanceTest.java           | 229 +++++++++++++++++++++
 .../xquery/springboot/XQueryConcurrencyTest.java   | 120 +++++++++++
 .../xquery/springboot/XQueryFilterTest.java        |  95 +++++++++
 .../springboot/XQueryFromFileExceptionTest.java    | 130 ++++++++++++
 .../xquery/springboot/XQueryFromFileTest.java      | 103 +++++++++
 ...XQueryHeaderNameResultTypeAndNamespaceTest.java |  93 +++++++++
 .../xquery/springboot/XQueryHeaderNameTest.java    | 126 ++++++++++++
 .../springboot/XQueryLanguageFromFileTest.java     | 110 ++++++++++
 .../springboot/XQueryPredicateFilterTest.java      |  99 +++++++++
 .../springboot/XQueryPropogateHeadersTest.java     | 125 +++++++++++
 .../xquery/springboot/XQueryRecipientListTest.java | 106 ++++++++++
 .../xquery/springboot/XQueryResourceTest.java      |  84 ++++++++
 .../springboot/XQueryTransformIssueTest.java       |  93 +++++++++
 .../xquery/springboot/XQueryTransformTest.java     |  86 ++++++++
 .../xquery/springboot/XQueryTransformTextTest.java |  84 ++++++++
 .../springboot/XQueryURLBasedConcurrencyTest.java  | 131 ++++++++++++
 .../xquery/springboot/XQueryWithExtensionTest.java | 151 ++++++++++++++
 .../xquery/springboot/XQueryWithFlworTest.java     |  79 +++++++
 .../springboot/XQueryWithNamespacesFilterTest.java |  98 +++++++++
 .../src/test/resources/log4j2.properties           |  28 +++
 .../src/test/resources/myinput.xml                 |  27 +++
 .../src/test/resources/myxquery.txt                |   1 +
 .../xquery/XQueryComponentConfigurationTest.xml    |  49 +++++
 .../xquery/XQueryEndpointConfigurationTest.xml     |  46 +++++
 .../apache/camel/component/xquery/camelContext.xml |  41 ++++
 .../camel/component/xquery/flwor-expression.xquery |   9 +
 .../camel/component/xquery/myTransform.xquery      |   4 +
 .../apache/camel/component/xquery/transform.xquery |   3 +
 .../component/xquery/transformWithExtension.xquery |   6 +
 .../component/xquery/transform_with_headers.xquery |   4 +
 .../camel/component/xquery/xqueryExampleTest.xml   |  37 ++++
 .../xquery/xqueryWithExplicitTypeContext.xml       |  38 ++++
 .../src/test/resources/payload.xml                 |  39 ++++
 41 files changed, 3206 insertions(+)

diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/BeanWithXQueryInjectionTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/BeanWithXQueryInjectionTest.java
new file mode 100644
index 0000000..d06c942
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/BeanWithXQueryInjectionTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.language.xquery.springboot;
+
+
+
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.xquery.XQuery;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        BeanWithXQueryInjectionTest.class,
+        BeanWithXQueryInjectionTest.TestConfiguration.class
+    }
+)
+public class BeanWithXQueryInjectionTest {
+    
+    private static final Logger LOG = LoggerFactory.getLogger(BeanWithXQueryInjectionTest.class);
+    
+    static MyBean myBean = new MyBean();
+
+    @Autowired
+    ProducerTemplate template;
+
+
+    @Bean("myBean") 
+    private MyBean getMyBean() {
+        return myBean;
+    }
+    
+    @Test
+    public void testSendMessage() throws Exception {
+        String expectedBody = "<foo id='bar'>hellow</foo>";
+
+        template.sendBodyAndHeader("direct:in", expectedBody, "foo", "bar");
+
+        assertEquals(expectedBody, myBean.body, "bean body: " + myBean);
+        assertEquals("bar", myBean.foo, "bean foo: " + myBean);
+    }
+
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("direct:in").bean("myBean");
+                }
+            };
+        }
+    }
+    
+    public static class MyBean {
+        public String body;
+        public String foo;
+
+        @Override
+        public String toString() {
+            return "MyBean[foo: " + foo + " body: " + body + "]";
+        }
+
+        public void read(String body, @XQuery("/foo/@id") String foo) {
+            this.foo = foo;
+            this.body = body;
+            LOG.info("read() method called on " + this);
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/FromFileBase.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/FromFileBase.java
new file mode 100644
index 0000000..a8ea7bb
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/FromFileBase.java
@@ -0,0 +1,73 @@
+/*
+ * 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.language.xquery.springboot;
+
+import static org.apache.camel.test.junit5.TestSupport.deleteDirectory;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class FromFileBase {
+    
+    private boolean testDirectoryCleaned;
+    
+    protected String fileUri() {
+        return "file:" + testDirectory();
+    }
+    
+    protected String fileUri(String query) {
+        return "file:" + testDirectory() + (query.startsWith("?") ? "" : "/") + query;
+    }
+    
+    protected Path testDirectory() {
+        return testDirectory(false);
+    }
+
+    protected Path testDirectory(boolean create) {
+        Class<?> testClass = getClass();
+        return testDirectory(testClass, create);
+    }
+
+    
+    
+    protected 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;
+    }
+    
+    protected Path testFile(String dir) {
+        return testDirectory().resolve(dir);
+    }
+    
+    public void deleteTestDirectory() {
+        if (!testDirectoryCleaned) {
+            deleteDirectory(testDirectory());
+            testDirectoryCleaned = true;
+        }
+    }
+    
+
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/SaxonLanguageExtensionFunctionsTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/SaxonLanguageExtensionFunctionsTest.java
new file mode 100644
index 0000000..98f086d
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/SaxonLanguageExtensionFunctionsTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.language.xquery.springboot;
+
+import net.sf.saxon.Configuration;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.language.xquery.XQueryLanguage;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+
+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;
+
+import org.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        SaxonLanguageExtensionFunctionsTest.class,
+        SaxonLanguageExtensionFunctionsTest.TestConfiguration.class
+    }
+)
+public class SaxonLanguageExtensionFunctionsTest {
+    
+    
+    @Autowired
+    ProducerTemplate template;
+    
+    @Autowired
+    CamelContext context;
+
+    @EndpointInject("mock:result")
+    protected MockEndpoint mock;   
+    
+    @Test
+    public void testWithExtension() throws Exception {
+        mock.expectedBodiesReceived("<transformed extension-function-render=\"arg1[test]\"/>");
+
+        template.sendBody("direct:start", "<body>test</body>");
+
+        mock.assertIsSatisfied();
+    }   
+
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @org.springframework.context.annotation.Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    Configuration conf = new Configuration();
+                    conf.registerExtensionFunction(new XQueryWithExtensionTest.SimpleExtension());
+
+                    XQueryLanguage xq = (XQueryLanguage) context.resolveLanguage("xquery");
+                    xq.setConfiguration(conf);
+
+                    from("direct:start")
+                            .transform()
+                            .xquery("resource:classpath:org/apache/camel/component/xquery/transformWithExtension.xquery")
+                            .to("mock:result");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/SaxonXPathSplitTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/SaxonXPathSplitTest.java
new file mode 100644
index 0000000..9ff97a0
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/SaxonXPathSplitTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.language.xquery.springboot;
+
+
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        SaxonXPathSplitTest.class,
+        SaxonXPathSplitTest.TestConfiguration.class
+    }
+)
+public class SaxonXPathSplitTest {
+    
+    
+    @Autowired
+    ProducerTemplate template;
+
+    @Autowired
+    CamelContext context;
+    
+    @EndpointInject("mock:london")
+    protected MockEndpoint mockLondon;   
+    
+    @EndpointInject("mock:paris")
+    protected MockEndpoint mockParis;
+    
+    @EndpointInject("mock:other")
+    protected MockEndpoint mockOther;
+    
+    @Test
+    public void testSaxonXPathSplit() throws Exception {
+        mockLondon.expectedMessageCount(1);
+        mockParis.expectedMessageCount(1);
+        mockOther.expectedMessageCount(1);
+
+        StringBuilder sb = new StringBuilder();
+        sb.append("<persons>");
+        sb.append("<person><city>London</city></person>");
+        sb.append("<person><city>Berlin</city></person>");
+        sb.append("<person><city>Paris</city></person>");
+        sb.append("</persons>");
+
+        template.sendBody("direct:start", sb.toString());
+
+        MockEndpoint.assertIsSatisfied(context);
+    }
+
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("direct:start")
+                            .split().xpath("/persons/person")
+                            .choice()
+                            .when().xpath("person/city = 'London'")
+                            .to("mock:london")
+                            .when().xpath("person/city = 'Paris'")
+                            .to("mock:paris")
+                            .otherwise()
+                            .to("mock:other");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/SaxonXPathTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/SaxonXPathTest.java
new file mode 100644
index 0000000..ecbad61
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/SaxonXPathTest.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.language.xquery.springboot;
+
+
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        SaxonXPathTest.class,
+        SaxonXPathTest.TestConfiguration.class
+    }
+)
+public class SaxonXPathTest {
+    
+    
+    @Autowired
+    ProducerTemplate template;
+
+    @Autowired
+    CamelContext context;
+    
+    @EndpointInject("mock:london")
+    protected MockEndpoint mockLondon;   
+    
+    @EndpointInject("mock:paris")
+    protected MockEndpoint mockParis;
+    
+    @EndpointInject("mock:other")
+    protected MockEndpoint mockOther;
+    
+    @Test
+    public void testSaxonXPathSplit() throws Exception {
+        mockLondon.expectedMessageCount(1);
+        mockParis.expectedMessageCount(1);
+        mockOther.expectedMessageCount(1);
+
+        template.sendBody("direct:start", "<person><city>London</city></person>");
+        template.sendBody("direct:start", "<person><city>Berlin</city></person>");
+        template.sendBody("direct:start", "<person><city>Paris</city></person>");
+
+        MockEndpoint.assertIsSatisfied(context);
+    }
+
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("direct:start")
+                            .choice()
+                            .when().xpath("person/city = 'London'")
+                            .to("mock:london")
+                            .when().xpath("person/city = 'Paris'")
+                            .to("mock:paris")
+                            .otherwise()
+                            .to("mock:other");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/SoapPayloadBean.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/SoapPayloadBean.java
new file mode 100644
index 0000000..9e51f9f
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/SoapPayloadBean.java
@@ -0,0 +1,35 @@
+/*
+ * 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.language.xquery.springboot;
+
+import org.w3c.dom.Document;
+
+import org.apache.camel.TypeConverter;
+import org.apache.camel.component.xquery.XQuery;
+import org.apache.camel.util.ObjectHelper;
+
+public class SoapPayloadBean {
+
+    public String doSomething(@XQuery("//payload") Document payload, TypeConverter converter) {
+        // grab the DOM payload
+        ObjectHelper.notNull(payload, "@XQuery payload");
+
+        // and convert it to a String which contains the xml tags
+        String xml = converter.convertTo(String.class, payload);
+        return xml;
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/SoapPayloadBeanTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/SoapPayloadBeanTest.java
new file mode 100644
index 0000000..80e67c4
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/SoapPayloadBeanTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.language.xquery.springboot;
+
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+
+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.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        SoapPayloadBeanTest.class,
+        SoapPayloadBeanTest.TestConfiguration.class
+    }
+)
+public class SoapPayloadBeanTest {
+    
+    
+    
+    @EndpointInject("mock:result")
+    protected MockEndpoint mock;   
+    
+    @Test
+    public void testSoapPayloadBean() throws Exception {
+        mock.expectedMessageCount(1);
+        mock.message(0).body().contains("<inputReportIncident>");
+        mock.message(0).body().contains("<incidentId>01</incidentId>");
+        mock.message(0).body().contains("<givenName>John</givenName>");
+        mock.message(0).body().endsWith("</inputReportIncident></payload>");
+
+        mock.assertIsSatisfied();
+    }
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("file:src/test/resources/?fileName=payload.xml&noop=true")
+                            .bean(SoapPayloadBean.class)
+                            .to("log:xml", "mock:result");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XPathHeaderEnableSaxonJavaDslTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XPathHeaderEnableSaxonJavaDslTest.java
new file mode 100644
index 0000000..bdfe369
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XPathHeaderEnableSaxonJavaDslTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.language.xquery.springboot;
+
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.language.xpath.XPathBuilder;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XPathHeaderEnableSaxonJavaDslTest.class,
+        XPathHeaderEnableSaxonJavaDslTest.TestConfiguration.class
+    }
+)
+public class XPathHeaderEnableSaxonJavaDslTest {
+    
+    
+    @Autowired
+    ProducerTemplate template;
+
+    @EndpointInject("mock:camel")
+    protected MockEndpoint camel;   
+    
+    @EndpointInject("mock:donkey")
+    protected MockEndpoint donkey;   
+    
+    @EndpointInject("mock:other")
+    protected MockEndpoint other;   
+    
+    @Test
+    public void testChoiceWithHeaderSelectCamel() throws Exception {
+        
+        camel.expectedBodiesReceived("<name>King</name>");
+        camel.expectedHeaderReceived("type", "Camel");
+
+        template.sendBodyAndHeader("direct:in", "<name>King</name>", "type", "Camel");
+
+        camel.assertIsSatisfied();
+    }
+
+    @Test
+    public void testChoiceWithNoHeaderSelectDonkey() throws Exception {
+        
+        donkey.expectedBodiesReceived("<name>Kong</name>");
+
+        template.sendBody("direct:in", "<name>Kong</name>");
+
+        donkey.assertIsSatisfied();
+    }
+
+    @Test
+    public void testChoiceWithNoHeaderSelectOther() throws Exception {
+        
+        other.expectedBodiesReceived("<name>Other</name>");
+
+        template.sendBody("direct:in", "<name>Other</name>");
+
+        other.assertIsSatisfied();
+    }
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("direct:in")
+                            .choice()
+                            .when(XPathBuilder.xpath("$type = 'Camel'").saxon())
+                            .to("mock:camel")
+                            .when(XPathBuilder.xpath("//name = 'Kong'").saxon())
+                            .to("mock:donkey")
+                            .otherwise()
+                            .to("mock:other");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XPathSplitChoicePerformanceTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XPathSplitChoicePerformanceTest.java
new file mode 100644
index 0000000..1e14964
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XPathSplitChoicePerformanceTest.java
@@ -0,0 +1,229 @@
+/*
+ * 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.language.xquery.springboot;
+
+
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.NotifyBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.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.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.apache.camel.util.StopWatch;
+import org.apache.camel.util.TimeUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XPathSplitChoicePerformanceTest.class,
+        XPathSplitChoicePerformanceTest.TestConfiguration.class
+    }
+)
+public class XPathSplitChoicePerformanceTest extends FromFileBase {
+    
+    private static final Logger LOG = LoggerFactory.getLogger(XPathSplitChoicePerformanceTest.class);
+    
+    private int size = 20 * 1000;
+    private final static AtomicInteger tiny = new AtomicInteger();
+    private final static AtomicInteger small = new AtomicInteger();
+    private final static AtomicInteger med = new AtomicInteger();
+    private final static AtomicInteger large = new AtomicInteger();
+    private final StopWatch watch = new StopWatch();
+
+    @Autowired
+    ProducerTemplate template;
+
+    @Autowired
+    CamelContext context;
+    
+    @EndpointInject("mock:result")
+    protected MockEndpoint mock;   
+    
+    
+    @BeforeEach
+    public void setUp() throws Exception {
+        createDataFile(LOG, size);
+    }
+
+    
+    @Test
+    //@Disabled("Manual test")
+    public void testXPathPerformanceRoute() throws Exception {
+        NotifyBuilder notify = new NotifyBuilder(context).whenDone(size).create();
+
+        boolean matches = notify.matches(60, TimeUnit.SECONDS);
+        LOG.info("Processed file with " + size + " elements in: " + TimeUtils.printDuration(watch.taken()));
+
+        LOG.info("Processed " + tiny.get() + " tiny messages");
+        LOG.info("Processed " + small.get() + " small messages");
+        LOG.info("Processed " + med.get() + " medium messages");
+        LOG.info("Processed " + large.get() + " large messages");
+
+        assertEquals((size / 10) * 4, tiny.get());
+        assertEquals((size / 10) * 2, small.get());
+        assertEquals((size / 10) * 3, med.get());
+        assertEquals((size / 10) * 1, large.get());
+
+        assertTrue(matches, "Should complete route");
+    }
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from(fileUri("?noop=true"))
+                            .process(new Processor() {
+                                public void process(Exchange exchange) throws Exception {
+                                    log.info("Starting to process file");
+                                    watch.restart();
+                                }
+                            })
+                            .split().xpath("/orders/order").streaming()
+                            .choice()
+                            .when().xpath("/order/amount < 10")
+                            .process(new Processor() {
+                                public void process(Exchange exchange) throws Exception {
+                                    String xml = exchange.getIn().getBody(String.class);
+                                    assertTrue(xml.contains("<amount>3</amount>"), xml);
+
+                                    int num = tiny.incrementAndGet();
+                                    if (num % 100 == 0) {
+                                        log.info("Processed " + num + " tiny messages");
+                                        log.debug(xml);
+                                    }
+                                }
+                            })
+                            .when().xpath("/order/amount < 50")
+                            .process(new Processor() {
+                                public void process(Exchange exchange) throws Exception {
+                                    String xml = exchange.getIn().getBody(String.class);
+                                    assertTrue(xml.contains("<amount>44</amount>"), xml);
+
+                                    int num = small.incrementAndGet();
+                                    if (num % 100 == 0) {
+                                        log.info("Processed " + num + " small messages");
+                                        log.debug(xml);
+                                    }
+                                }
+                            })
+                            .when().xpath("/order/amount < 100")
+                            .process(new Processor() {
+                                public void process(Exchange exchange) throws Exception {
+                                    String xml = exchange.getIn().getBody(String.class);
+                                    assertTrue(xml.contains("<amount>88</amount>"), xml);
+
+                                    int num = med.incrementAndGet();
+                                    if (num % 100 == 0) {
+                                        log.info("Processed " + num + " medium messages");
+                                        log.debug(xml);
+                                    }
+                                }
+                            })
+                            .otherwise()
+                            .process(new Processor() {
+                                public void process(Exchange exchange) throws Exception {
+                                    String xml = exchange.getIn().getBody(String.class);
+                                    assertTrue(xml.contains("<amount>123</amount>"), xml);
+
+                                    int num = large.incrementAndGet();
+                                    if (num % 100 == 0) {
+                                        log.info("Processed " + num + " large messages");
+                                        log.debug(xml);
+                                    }
+                                }
+                            })
+                            .end() // choice
+                            .end(); // split
+                }
+            };
+        }
+    }
+    
+    public void createDataFile(Logger log, int size) throws Exception {
+        deleteTestDirectory();
+
+        log.info("Creating data file ...");
+
+        File file = testDirectory(true).resolve("data.xml").toFile();
+        FileOutputStream fos = new FileOutputStream(file, true);
+        fos.write("<orders>\n".getBytes());
+
+        for (int i = 0; i < size; i++) {
+            fos.write("<order>\n".getBytes());
+            fos.write(("  <id>" + i + "</id>\n").getBytes());
+            int num = i % 10;
+            if (num >= 0 && num <= 3) {
+                fos.write("  <amount>3</amount>\n".getBytes());
+                fos.write("  <customerId>333</customerId>\n".getBytes());
+            } else if (num >= 4 && num <= 5) {
+                fos.write("  <amount>44</amount>\n".getBytes());
+                fos.write("  <customerId>444</customerId>\n".getBytes());
+            } else if (num >= 6 && num <= 8) {
+                fos.write("  <amount>88</amount>\n".getBytes());
+                fos.write("  <customerId>888</customerId>\n".getBytes());
+            } else {
+                fos.write("  <amount>123</amount>\n".getBytes());
+                fos.write("  <customerId>123123</customerId>\n".getBytes());
+            }
+            fos.write("  <description>bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla</description>\n"
+                    .getBytes());
+            fos.write("</order>\n".getBytes());
+        }
+
+        fos.write("</orders>".getBytes());
+        fos.close();
+
+        log.info("Creating data file done.");
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryConcurrencyTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryConcurrencyTest.java
new file mode 100644
index 0000000..e268044
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryConcurrencyTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.language.xquery.springboot;
+
+
+import static org.apache.camel.test.junit5.TestSupport.body;
+
+import java.security.SecureRandom;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.test.annotation.DirtiesContext;
+
+import org.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XQueryConcurrencyTest.class,
+        XQueryConcurrencyTest.TestConfiguration.class
+    }
+)
+public class XQueryConcurrencyTest {
+    
+    private String uri = "seda:in?concurrentConsumers=5";
+
+    @Autowired
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    protected MockEndpoint mock;   
+    
+    @Test
+    public void testConcurrency() throws Exception {
+        int total = 1000;
+
+        mock.expectedMessageCount(total);
+
+        // setup a task executor to be able send the messages in parallel
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setCorePoolSize(5);
+        executor.afterPropertiesSet();
+        for (int i = 0; i < 5; i++) {
+            final int threadCount = i;
+            executor.execute(new Runnable() {
+                public void run() {
+                    int start = threadCount * 200;
+                    for (int i = 0; i < 200; i++) {
+                        try {
+                            // do some random sleep to simulate spread in user activity
+                            Thread.sleep(new SecureRandom().nextInt(10));
+                        } catch (InterruptedException e) {
+                            // ignore
+                        }
+                        template.sendBody(uri, "<person><id>" + (start + i + 1) + "</id><name>James</name></person>");
+                    }
+                }
+            });
+        }
+
+        mock.assertNoDuplicates(body());
+
+        mock.assertIsSatisfied();
+        executor.shutdown();
+    }
+
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    // no retry as we want every failure to submerge
+                    errorHandler(noErrorHandler());
+
+                    from(uri)
+                            .transform().xquery("/person/id", String.class)
+                            .to("mock:result");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryFilterTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryFilterTest.java
new file mode 100644
index 0000000..09f86a0
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryFilterTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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.language.xquery.springboot;
+
+
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XQueryFilterTest.class,
+        XQueryFilterTest.TestConfiguration.class
+    }
+)
+public class XQueryFilterTest {
+    
+    
+    @Autowired
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    protected MockEndpoint resultEndpoint;   
+    
+    @Test
+    public void testSendMatchingMessage() throws Exception {
+        resultEndpoint.reset();
+        resultEndpoint.expectedMessageCount(1);
+
+        template.sendBody("direct:start", "<person name='James' city='London'/>");
+
+        resultEndpoint.assertIsSatisfied();
+    }
+
+    @Test
+    public void testSendNotMatchingMessage() throws Exception {
+        resultEndpoint.reset();
+        resultEndpoint.expectedMessageCount(0);
+
+        template.sendBody("direct:start", "<person name='Hiram' city='Tampa'/>");
+
+        resultEndpoint.assertIsSatisfied();
+    }
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    // START SNIPPET: example
+                    from("direct:start").filter().xquery("/person[@name='James']").to("mock:result");
+                    // END SNIPPET: example
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryFromFileExceptionTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryFromFileExceptionTest.java
new file mode 100644
index 0000000..bc5117c
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryFromFileExceptionTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.language.xquery.springboot;
+
+
+import static org.apache.camel.test.junit5.TestSupport.assertFileExists;
+import static org.apache.camel.test.junit5.TestSupport.assertFileNotExists;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XQueryFromFileExceptionTest.class,
+        XQueryFromFileExceptionTest.TestConfiguration.class
+    }
+)
+public class XQueryFromFileExceptionTest extends FromFileBase {
+    
+    @Autowired
+    ProducerTemplate template;
+    
+    @Autowired
+    CamelContext context;
+
+    @EndpointInject("mock:result")
+    protected MockEndpoint mock;
+    
+    
+    
+    @EndpointInject("mock:error")
+    protected MockEndpoint error;  
+    
+    @Test
+    public void testXQueryFromFileExceptionOk() throws Exception {
+        mock.reset();
+        mock.expectedMessageCount(1);
+        error.expectedMessageCount(0);
+
+        String body = "<person user='James'><firstName>James</firstName>"
+                      + "<lastName>Strachan</lastName><city>London</city></person>";
+        template.sendBodyAndHeader(fileUri(), body, Exchange.FILE_NAME, "hello.xml");
+
+        MockEndpoint.assertIsSatisfied(context);
+
+        Thread.sleep(500);
+
+        assertFileNotExists(testFile("hello.xml"));
+        assertFileExists(testFile("ok/hello.xml"));
+    }
+
+    @Test
+    public void testXQueryFromFileExceptionFail() throws Exception {
+        mock.reset();
+        mock.expectedMessageCount(0);
+        error.expectedMessageCount(1);
+
+        // the last tag is not ended properly
+        String body = "<person user='James'><firstName>James</firstName>"
+                      + "<lastName>Strachan</lastName><city>London</city></person";
+        template.sendBodyAndHeader(fileUri(), body, Exchange.FILE_NAME, "hello2.xml");
+
+        MockEndpoint.assertIsSatisfied(context);
+
+        Thread.sleep(500);
+
+        assertFileNotExists(testFile("hello2.xml"));
+        assertFileExists(testFile("error/hello2.xml"));
+    }
+
+    
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from(fileUri("?moveFailed=error&move=ok"))
+                            .onException(Exception.class)
+                            .to("mock:error")
+                            .end()
+                            .to("xquery:org/apache/camel/component/xquery/myTransform.xquery")
+                            .to("mock:result");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryFromFileTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryFromFileTest.java
new file mode 100644
index 0000000..96a6aca
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryFromFileTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.language.xquery.springboot;
+
+
+import java.util.List;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XQueryFromFileTest.class,
+        XQueryFromFileTest.TestConfiguration.class
+    }
+)
+public class XQueryFromFileTest extends FromFileBase {
+
+    @Autowired
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    protected MockEndpoint mock; 
+      
+    @Test
+    public void testXQueryFromFile() throws Exception {
+        
+        mock.expectedMessageCount(1);
+
+        template.sendBodyAndHeader(fileUri(), "<mail><subject>Hey</subject><body>Hello world!</body></mail>",
+                Exchange.FILE_NAME, "body.xml");
+
+        mock.assertIsSatisfied();
+
+        List<Exchange> list = mock.getReceivedExchanges();
+        Exchange exchange = list.get(0);
+        String xml = exchange.getIn().getBody(String.class);
+        assertNotNull(xml, "The transformed XML should not be null");
+        assertEquals("<transformed subject=\"Hey\"><mail><subject>Hey</subject>"
+                     + "<body>Hello world!</body></mail></transformed>",
+                xml, "transformed");
+    }
+
+    
+
+    
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from(fileUri())
+                            .to("xquery:org/apache/camel/component/xquery/transform.xquery")
+                            .to("mock:result");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryHeaderNameResultTypeAndNamespaceTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryHeaderNameResultTypeAndNamespaceTest.java
new file mode 100644
index 0000000..55e3209
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryHeaderNameResultTypeAndNamespaceTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.language.xquery.springboot;
+
+
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+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.builder.Namespaces;
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XQueryHeaderNameResultTypeAndNamespaceTest.class,
+        XQueryHeaderNameResultTypeAndNamespaceTest.TestConfiguration.class
+    }
+)
+public class XQueryHeaderNameResultTypeAndNamespaceTest {
+    
+    
+    @Autowired
+    ProducerTemplate template;
+
+    @EndpointInject("mock:55")
+    protected MockEndpoint mock;   
+    
+    @Test
+    public void testXPathWithNamespace() throws Exception {
+        
+        mock.expectedBodiesReceived("body");
+        mock.expectedHeaderReceived("cheeseDetails", "<number xmlns=\"http://acme.com/cheese\">55</number>");
+
+        template.sendBodyAndHeader("direct:in", "body", "cheeseDetails",
+                "<number xmlns=\"http://acme.com/cheese\">55</number>");
+
+        mock.assertIsSatisfied();
+    }
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    Namespaces ns = new Namespaces("c", "http://acme.com/cheese");
+
+                    from("direct:in").choice()
+                            .when().xquery("/c:number = 55", Integer.class, ns, "cheeseDetails")
+                            .to("mock:55")
+                            .otherwise()
+                            .to("mock:other")
+                            .end();
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryHeaderNameTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryHeaderNameTest.java
new file mode 100644
index 0000000..c39b1e3
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryHeaderNameTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.language.xquery.springboot;
+
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XQueryHeaderNameTest.class,
+        XQueryHeaderNameTest.TestConfiguration.class
+    }
+)
+public class XQueryHeaderNameTest {
+    
+    
+    @Autowired
+    ProducerTemplate template;
+
+    @EndpointInject("mock:premium")
+    protected MockEndpoint premium;   
+    
+    @EndpointInject("mock:unknown")
+    protected MockEndpoint unknown; 
+    
+    @EndpointInject("mock:standard")
+    protected MockEndpoint standard; 
+    
+    @Test
+    public void testChoiceWithHeaderNamePremium() throws Exception {
+        
+        premium.expectedBodiesReceived("<response>OK</response>");
+        premium.expectedHeaderReceived("invoiceDetails",
+                "<invoice orderType='premium'><person><name>Alan</name></person></invoice>");
+
+        template.sendBodyAndHeader("direct:in", "<response>OK</response>",
+                "invoiceDetails", "<invoice orderType='premium'><person><name>Alan</name></person></invoice>");
+
+        premium.assertIsSatisfied();
+    }
+
+    @Test
+    public void testChoiceWithHeaderNameStandard() throws Exception {
+        
+        standard.expectedBodiesReceived("<response>OK</response>");
+        standard.expectedHeaderReceived("invoiceDetails",
+                "<invoice orderType='standard'><person><name>Alan</name></person></invoice>");
+
+        template.sendBodyAndHeader("direct:in", "<response>OK</response>",
+                "invoiceDetails", "<invoice orderType='standard'><person><name>Alan</name></person></invoice>");
+
+        standard.assertIsSatisfied();
+    }
+
+    @Test
+    public void testChoiceWithHeaderNameUnknown() throws Exception {
+        
+        unknown.expectedBodiesReceived("<response>OK</response>");
+        unknown.expectedHeaderReceived("invoiceDetails", "<invoice />");
+
+        template.sendBodyAndHeader("direct:in", "<response>OK</response>",
+                "invoiceDetails", "<invoice />");
+
+        unknown.assertIsSatisfied();
+    }
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("direct:in")
+                            .choice()
+                            .when().xquery("/invoice/@orderType = 'premium'", "invoiceDetails")
+                            .to("mock:premium")
+                            .when().xquery("/invoice/@orderType = 'standard'", "invoiceDetails")
+                            .to("mock:standard")
+                            .otherwise()
+                            .to("mock:unknown")
+                            .end();
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryLanguageFromFileTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryLanguageFromFileTest.java
new file mode 100644
index 0000000..6c4afd9
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryLanguageFromFileTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.language.xquery.springboot;
+
+
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XQueryLanguageFromFileTest.class,
+        XQueryLanguageFromFileTest.TestConfiguration.class
+    }
+)
+public class XQueryLanguageFromFileTest extends FromFileBase {
+
+    @Autowired
+    private CamelContext context;
+    
+    @Autowired
+    ProducerTemplate template;
+
+    @EndpointInject("mock:davsclaus")
+    MockEndpoint mock;
+
+    @EndpointInject("mock:other")
+    MockEndpoint other;
+    
+    @Test
+    public void testXQueryFromFile() throws Exception {
+        
+        mock.expectedMessageCount(1);
+        mock.message(0).body(String.class).contains("Hello World");
+
+        
+        other.expectedMessageCount(1);
+        other.message(0).body(String.class).contains("Bye World");
+
+        template.sendBodyAndHeader(fileUri(),
+                "<mail from=\"davsclaus@apache.org\"><subject>Hey</subject><body>Hello World!</body></mail>",
+                Exchange.FILE_NAME, "claus.xml");
+
+        template.sendBodyAndHeader(fileUri(),
+                "<mail from=\"janstey@apache.org\"><subject>Hey</subject><body>Bye World!</body></mail>",
+                Exchange.FILE_NAME, "janstey.xml");
+
+        MockEndpoint.assertIsSatisfied(context);
+    }
+
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from(fileUri())
+                            .choice()
+                            .when().xquery("/mail/@from = 'davsclaus@apache.org'")
+                            .convertBodyTo(String.class)
+                            .to("mock:davsclaus")
+                            .otherwise()
+                            .convertBodyTo(String.class)
+                            .to("mock:other");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryPredicateFilterTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryPredicateFilterTest.java
new file mode 100644
index 0000000..b8c8bb9
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryPredicateFilterTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.language.xquery.springboot;
+
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.language.xpath.XPathBuilder;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XQueryPredicateFilterTest.class,
+        XQueryPredicateFilterTest.TestConfiguration.class
+    }
+)
+public class XQueryPredicateFilterTest {
+
+    @Autowired
+    @Produce("direct:xpath")
+    ProducerTemplate template;
+    
+    @Autowired
+    CamelContext context;
+
+    @EndpointInject("mock:result")
+    protected MockEndpoint resultEndpoint;  
+    
+    @Test
+    public void testXQuerySplitter() throws Exception {
+        resultEndpoint.expectedMessageCount(1);
+        template.sendBody("<records><record><type>1</type></record><record><type>2</type></record></records>");
+        resultEndpoint.assertIsSatisfied();
+
+        resultEndpoint.reset();
+        template.sendBody("<records><record><type>3</type></record><record><type>4</type></record></records>");
+        resultEndpoint.expectedMessageCount(0);
+        resultEndpoint.assertIsSatisfied();
+    }
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+
+                    XPathBuilder splitter = new XPathBuilder("//records/record");
+
+                    context.setTracing(true);
+
+                    from("direct:xpath").split(splitter).filter().xquery("//record[type=2]")
+                            .to("mock:result");
+
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryPropogateHeadersTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryPropogateHeadersTest.java
new file mode 100644
index 0000000..b0da933
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryPropogateHeadersTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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.language.xquery.springboot;
+
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XQueryPropogateHeadersTest.class,
+        XQueryPropogateHeadersTest.TestConfiguration.class
+    }
+)
+public class XQueryPropogateHeadersTest {
+    
+    
+    @Autowired
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    protected MockEndpoint mock;   
+    
+    @Test
+    public void testPropogateHeadersTest() throws Exception {
+        mock.reset();
+        mock.expectedMessageCount(1);
+        mock.expectedBodiesReceived("<transformed sender=\"bar\" subject=\"Hey\"><mail><subject>Hey</subject>"
+                                    + "<body>Hello world!</body></mail></transformed>");
+        mock.expectedHeaderReceived("foo", "bar");
+
+        template.sendBodyAndHeader("direct:one",
+                "<mail><subject>Hey</subject><body>Hello world!</body></mail>", "foo", "bar");
+
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    public void testPropogateHeadersUsingTransform() throws Exception {
+        mock.reset();
+        mock.expectedMessageCount(1);
+        mock.expectedBodiesReceived("London");
+        mock.expectedHeaderReceived("foo", "bar");
+
+        template.sendBodyAndHeader("direct:two",
+                "<person name='James' city='London'/>", "foo", "bar");
+
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    public void testPropogateHeadersUsingSetBody() throws Exception {
+        mock.reset();
+        mock.expectedMessageCount(1);
+        mock.expectedBodiesReceived("London");
+        mock.expectedHeaderReceived("foo", "bar");
+
+        template.sendBodyAndHeader("direct:three",
+                "<person name='James' city='London'/>", "foo", "bar");
+
+        mock.assertIsSatisfied();
+    }
+
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("direct:one")
+                            .to("xquery:org/apache/camel/component/xquery/transform_with_headers.xquery")
+                            .to("mock:result");
+
+                    from("direct:two")
+                            .transform().xquery("/person/@city", String.class)
+                            .to("mock:result");
+
+                    from("direct:three")
+                            .setBody().xquery("/person/@city", String.class)
+                            .to("mock:result");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryRecipientListTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryRecipientListTest.java
new file mode 100644
index 0000000..17a4c64
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryRecipientListTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.language.xquery.springboot;
+
+
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XQueryRecipientListTest.class,
+        XQueryRecipientListTest.TestConfiguration.class
+    }
+)
+public class XQueryRecipientListTest {
+    
+    
+    @Autowired
+    ProducerTemplate template;
+    
+    @Autowired
+    CamelContext context;
+
+    @EndpointInject("mock:foo.London")
+    protected MockEndpoint londonEndpoint;   
+    
+    @EndpointInject("mock:foo.Tampa")
+    protected MockEndpoint tampaEndpoint;   
+    
+    @Test
+    public void testSendLondonMessage() throws Exception {
+        MockEndpoint.resetMocks(context);
+        londonEndpoint.expectedMessageCount(1);
+        tampaEndpoint.expectedMessageCount(0);
+
+        template.sendBody("direct:start", "<person name='James' city='London'/>");
+        MockEndpoint.assertIsSatisfied(context);
+        
+    }
+
+    @Test
+    public void testSendTampaMessage() throws Exception {
+        MockEndpoint.resetMocks(context);
+        londonEndpoint.expectedMessageCount(0);
+        tampaEndpoint.expectedMessageCount(1);
+
+        template.sendBody("direct:start", "<person name='Hiram' city='Tampa'/>");
+
+        MockEndpoint.assertIsSatisfied(context);
+    }
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    // TODO is there a nicer way to do this with XQuery?
+
+                    // START SNIPPET: example
+                    from("direct:start").recipientList().xquery("concat('mock:foo.', /person/@city)", String.class);
+                    // END SNIPPET: example
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryResourceTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryResourceTest.java
new file mode 100644
index 0000000..db0d796
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryResourceTest.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.language.xquery.springboot;
+
+
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XQueryResourceTest.class,
+        XQueryResourceTest.TestConfiguration.class
+    }
+)
+public class XQueryResourceTest {
+    
+    
+    @Autowired
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    protected MockEndpoint mock;   
+    
+    @Test
+    public void testXPathResource() throws Exception {
+        mock.expectedBodiesReceived("London");
+
+        template.sendBody("direct:start", "<person name='James' city='London'/>");
+
+        mock.assertIsSatisfied();
+    }
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("direct:start")
+                            .transform().xquery("resource:classpath:myxquery.txt", String.class)
+                            .to("mock:result");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryTransformIssueTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryTransformIssueTest.java
new file mode 100644
index 0000000..9696869
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryTransformIssueTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.language.xquery.springboot;
+
+
+
+import java.io.FileInputStream;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.apache.camel.util.IOHelper;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XQueryTransformIssueTest.class,
+        XQueryTransformIssueTest.TestConfiguration.class
+    }
+)
+public class XQueryTransformIssueTest {
+    
+    
+    @Autowired
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    protected MockEndpoint mock;   
+    
+    @Test
+    public void testTransform() throws Exception {
+        String data = IOHelper.loadText(new FileInputStream("src/test/resources/myinput.xml"));
+
+        mock.expectedBodiesReceived("123TestConcat");
+
+        template.sendBody("direct:start", data);
+
+        mock.assertIsSatisfied();
+    }
+
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("direct:start")
+                            .transform().xquery("concat(/Envelope/Body/getEmployee/EmpId/text(),\"TestConcat\")", String.class)
+                            .to("log:info")
+                            .to("mock:result");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryTransformTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryTransformTest.java
new file mode 100644
index 0000000..6a0abad
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryTransformTest.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.language.xquery.springboot;
+
+
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XQueryTransformTest.class,
+        XQueryTransformTest.TestConfiguration.class
+    }
+)
+public class XQueryTransformTest {
+    
+    
+    @Autowired
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    protected MockEndpoint resultEndpoint;   
+    
+    @Test
+    public void testSendMatchingMessage() throws Exception {
+        // saxon converts all quotes to "
+        resultEndpoint.expectedBodiesReceived("<person name=\"Jonathan\"/>");
+
+        template.sendBody("direct:start", "<people><person name='Jonathan'/></people>");
+
+        resultEndpoint.assertIsSatisfied();
+    }
+
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    // START SNIPPET: example
+                    from("direct:start").transform().xquery("/people/person[@name='Jonathan']").to("mock:result");
+                    // END SNIPPET: example
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryTransformTextTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryTransformTextTest.java
new file mode 100644
index 0000000..c214bdb
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryTransformTextTest.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.language.xquery.springboot;
+
+
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XQueryTransformTextTest.class,
+        XQueryTransformTextTest.TestConfiguration.class
+    }
+)
+public class XQueryTransformTextTest {
+    
+    
+    @Autowired
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    protected MockEndpoint resultEndpoint;   
+    
+    @Test
+    public void testSendMatchingMessage() throws Exception {
+        // saxon converts all quotes to "
+        resultEndpoint.expectedBodiesReceived("Jonathan");
+
+        template.sendBody("direct:start", "<people><person>Jonathan</person></people>");
+
+        resultEndpoint.assertIsSatisfied();
+    }
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    // START SNIPPET: example
+                    from("direct:start").transform().xquery("/people/person/text()", String.class).to("mock:result");
+                    // END SNIPPET: example
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryURLBasedConcurrencyTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryURLBasedConcurrencyTest.java
new file mode 100644
index 0000000..53ff978
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryURLBasedConcurrencyTest.java
@@ -0,0 +1,131 @@
+/*
+ * 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.language.xquery.springboot;
+
+
+import static org.apache.camel.test.junit5.TestSupport.bodyAs;
+
+import java.security.SecureRandom;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.test.annotation.DirtiesContext;
+
+import org.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XQueryURLBasedConcurrencyTest.class,
+        XQueryURLBasedConcurrencyTest.TestConfiguration.class
+    }
+)
+public class XQueryURLBasedConcurrencyTest {
+
+    @Autowired
+    ProducerTemplate template;
+    
+    @Autowired
+    CamelContext context;
+    
+    @EndpointInject("mock:result")
+    MockEndpoint mock;
+
+      
+    @Test
+    public void testConcurrency() throws Exception {
+        int total = 1000;
+
+        
+        mock.expectedMessageCount(total);
+
+        // setup a task executor to be able send the messages in parallel
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setCorePoolSize(5);
+        executor.afterPropertiesSet();
+        for (int i = 0; i < 5; i++) {
+            final int threadCount = i;
+            executor.execute(new Runnable() {
+                public void run() {
+                    int start = threadCount * 200;
+                    for (int i = 0; i < 200; i++) {
+                        try {
+                            // do some random sleep to simulate spread in user activity
+                            Thread.sleep(new SecureRandom().nextInt(10));
+                        } catch (InterruptedException e) {
+                            // ignore
+                        }
+                        if (context.getStatus().isStarted()) {
+                            template.sendBody("direct:start",
+                                    "<mail><subject>" + (start + i) + "</subject><body>Hello world!</body></mail>");
+                        }
+                    }
+                }
+            });
+        }
+
+        mock.setResultWaitTime(30000);
+        mock.assertIsSatisfied();
+        // must use bodyAs(String.class) to force DOM to be converted to String XML
+        // for duplication detection
+        mock.assertNoDuplicates(bodyAs(String.class));
+        executor.shutdown();
+    }
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    // no retry as we want every failure to submerge
+                    errorHandler(noErrorHandler());
+
+                    from("direct:start").to("seda:foo?concurrentConsumers=5");
+
+                    from("seda:foo?concurrentConsumers=5")
+                            .to("xquery:org/apache/camel/component/xquery/transform.xquery")
+                            .to("log:result?groupSize=100")
+                            .to("mock:result");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryWithExtensionTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryWithExtensionTest.java
new file mode 100644
index 0000000..e93f225
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryWithExtensionTest.java
@@ -0,0 +1,151 @@
+/*
+ * 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.language.xquery.springboot;
+
+import net.sf.saxon.expr.XPathContext;
+import net.sf.saxon.lib.ExtensionFunctionCall;
+import net.sf.saxon.lib.ExtensionFunctionDefinition;
+import net.sf.saxon.om.Item;
+import net.sf.saxon.om.Sequence;
+import net.sf.saxon.om.StructuredQName;
+import net.sf.saxon.trans.XPathException;
+import net.sf.saxon.value.SequenceType;
+import net.sf.saxon.value.StringValue;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XQueryWithExtensionTest.class,
+        XQueryWithExtensionTest.TestConfiguration.class
+    }
+)
+public class XQueryWithExtensionTest {
+    
+    
+    @Autowired
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    protected MockEndpoint mock;   
+    
+    private net.sf.saxon.Configuration conf;
+
+    @Bean("saxonConf")
+    public net.sf.saxon.Configuration loadConf() throws Exception {
+
+        conf = new net.sf.saxon.Configuration();
+        conf.registerExtensionFunction(new SimpleExtension());
+
+        return conf;
+    }
+
+    @Test
+    public void testWithExtension() throws Exception {
+        
+        mock.expectedBodiesReceived("<transformed extension-function-render=\"arg1[test]\"/>");
+
+        template.sendBody("direct:start", "<body>test</body>");
+
+        mock.assertIsSatisfied();
+    }
+
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("direct:start")
+                            .to("xquery:org/apache/camel/component/xquery/transformWithExtension.xquery?configuration=#saxonConf")
+                            .to("mock:result");
+                }
+            };
+        }
+    }
+    
+    
+    /**
+     * This is a very simple example of a saxon extension function. We will use this for testing purposes.
+     * <p/>
+     * Example: <code>efx:simple('some text')</code> will be rendered to <code>arg1[some text]</code> and returned in
+     * the XQuery response.
+     */
+    public static final class SimpleExtension extends ExtensionFunctionDefinition {
+
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public SequenceType[] getArgumentTypes() {
+            return new SequenceType[] { SequenceType.SINGLE_STRING };
+        }
+
+        @Override
+        public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) {
+            return SequenceType.SINGLE_STRING;
+        }
+
+        @Override
+        public StructuredQName getFunctionQName() {
+            return new StructuredQName("efx", "http://test/saxon/ext", "simple");
+        }
+
+        @Override
+        public ExtensionFunctionCall makeCallExpression() {
+            return new ExtensionFunctionCall() {
+
+
+                @Override
+                public Sequence call(XPathContext xPathContext, Sequence[] sequences) throws XPathException {
+                    // get value of first arg passed to the function
+                    Item arg1 = sequences[0].head();
+                    String arg1Val = arg1.getStringValue();
+
+                    // return a altered version of the first arg
+                    return new StringValue("arg1[" + arg1Val + "]");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryWithFlworTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryWithFlworTest.java
new file mode 100644
index 0000000..5e73b98
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryWithFlworTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.language.xquery.springboot;
+
+
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XQueryWithFlworTest.class,
+        XQueryWithFlworTest.TestConfiguration.class
+    }
+)
+public class XQueryWithFlworTest {
+
+    @Autowired
+    ProducerTemplate template;
+
+      
+    @Test
+    public void testWithFlworExpression() {
+        String xml
+                = "<items><item><id>3</id><name>third</name></item><item><id>1</id><name>first</name></item><item><id>2</id><name>second</name></item></items>";
+        String expectedOrderedIds = "<base><id>1</id><id>3</id></base>";
+        String orderedIds = template.requestBody("direct:flwor-expression", xml, String.class);
+        assertEquals(expectedOrderedIds, orderedIds);
+    }
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("direct:flwor-expression").to("xquery:org/apache/camel/component/xquery/flwor-expression.xquery");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryWithNamespacesFilterTest.java b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryWithNamespacesFilterTest.java
new file mode 100644
index 0000000..b8c7b33
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/java/org/apache/camel/language/xquery/springboot/XQueryWithNamespacesFilterTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.language.xquery.springboot;
+
+
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+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.builder.Namespaces;
+import org.springframework.beans.factory.annotation.Autowired;
+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.junit.jupiter.api.Test;
+
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        XQueryWithNamespacesFilterTest.class,
+        XQueryWithNamespacesFilterTest.TestConfiguration.class
+    }
+)
+public class XQueryWithNamespacesFilterTest {
+    
+    
+    @Autowired
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    protected MockEndpoint mock;   
+    
+    @Test
+    public void testSendMatchingMessage() throws Exception {
+        mock.reset();
+        mock.expectedMessageCount(1);
+
+        template.sendBody("direct:start", "<person xmlns='http://acme.com/cheese' name='James' city='London'/>");
+
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    public void testSendNotMatchingMessage() throws Exception {
+        mock.reset();
+        mock.expectedMessageCount(0);
+
+        template.sendBody("direct:start", "<person xmlns='http://acme.com/cheese'  name='Hiram' city='Tampa'/>");
+
+        mock.assertIsSatisfied();
+    }
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    // START SNIPPET: example
+                    Namespaces ns = new Namespaces("c", "http://acme.com/cheese");
+
+                    from("direct:start").filter().xquery("/c:person[@name='James']", ns).to("mock:result");
+                    // END SNIPPET: example
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-saxon-starter/src/test/resources/log4j2.properties b/components-starter/camel-saxon-starter/src/test/resources/log4j2.properties
new file mode 100644
index 0000000..2de3421
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/resources/log4j2.properties
@@ -0,0 +1,28 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-saxon-test.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+appender.out.type = Console
+appender.out.name = out
+appender.out.layout.type = PatternLayout
+appender.out.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+rootLogger.level = INFO
+rootLogger.appenderRef.file.ref = file
diff --git a/components-starter/camel-saxon-starter/src/test/resources/myinput.xml b/components-starter/camel-saxon-starter/src/test/resources/myinput.xml
new file mode 100644
index 0000000..d7ca32e
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/resources/myinput.xml
@@ -0,0 +1,27 @@
+<?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.
+
+-->
+<Envelope>
+  <Header/>
+  <Body>
+    <getEmployee>
+      <EmpId>123</EmpId>
+    </getEmployee>
+  </Body>
+</Envelope>
\ No newline at end of file
diff --git a/components-starter/camel-saxon-starter/src/test/resources/myxquery.txt b/components-starter/camel-saxon-starter/src/test/resources/myxquery.txt
new file mode 100644
index 0000000..f583d99
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/resources/myxquery.txt
@@ -0,0 +1 @@
+/person/@city
\ No newline at end of file
diff --git a/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/XQueryComponentConfigurationTest.xml b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/XQueryComponentConfigurationTest.xml
new file mode 100644
index 0000000..5752105
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/XQueryComponentConfigurationTest.xml
@@ -0,0 +1,49 @@
+<?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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+         http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
+      ">
+
+  <bean id="xquery" class="org.apache.camel.component.xquery.XQueryComponent">
+    <property name="configuration">
+      <bean class="net.sf.saxon.Configuration"/>
+    </property>
+    <property name="configurationProperties">
+      <map>
+        <entry key="http://saxon.sf.net/feature/allow-external-functions" value="false" value-type="java.lang.Boolean"/>
+      </map>
+    </property>
+  </bean>
+
+  <!-- START SNIPPET: example -->
+  <camelContext xmlns="http://camel.apache.org/schema/spring">
+    <route>
+      <from uri="direct:start"/>
+      <to uri="xquery:org/apache/camel/component/xquery/transform.xquery"/>
+      <to uri="mock:result"/>
+    </route>
+  </camelContext>
+  <!-- END SNIPPET: example -->
+
+
+</beans>
diff --git a/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/XQueryEndpointConfigurationTest.xml b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/XQueryEndpointConfigurationTest.xml
new file mode 100644
index 0000000..5da9c90
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/XQueryEndpointConfigurationTest.xml
@@ -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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xsi:schemaLocation="
+         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+         http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
+         http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
+      ">
+
+  <bean id="saxon-configuration" class="net.sf.saxon.Configuration"/>
+
+  <util:map id="saxon-properties" key-type="java.lang.String" value-type="java.lang.Object">
+    <entry key="http://saxon.sf.net/feature/allow-external-functions" value="false" value-type="java.lang.Boolean"/>
+  </util:map>
+
+  <!-- START SNIPPET: example -->
+  <camelContext xmlns="http://camel.apache.org/schema/spring">
+    <route>
+      <from uri="direct:start"/>
+      <to uri="xquery:org/apache/camel/component/xquery/transform.xquery?configuration=#saxon-configuration&amp;configurationProperties=#saxon-properties"/>
+      <to uri="mock:result"/>
+    </route>
+  </camelContext>
+  <!-- END SNIPPET: example -->
+
+
+</beans>
diff --git a/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/camelContext.xml b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/camelContext.xml
new file mode 100644
index 0000000..31460e7
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/camelContext.xml
@@ -0,0 +1,41 @@
+<?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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
+    ">
+
+  <!-- START SNIPPET: example -->
+  <camelContext xmlns="http://camel.apache.org/schema/spring">
+    <route>
+      <from uri="direct:start"/>
+      <to uri="xquery:org/apache/camel/component/xquery/transform.xquery"/>
+      <multicast>
+        <bean ref="testBean"/>
+        <to uri="mock:result"/>
+      </multicast>
+    </route>
+  </camelContext>
+  <!-- END SNIPPET: example -->
+
+  <bean id="testBean" class="org.apache.camel.component.xquery.TestBean" scope="singleton"/>
+</beans>
diff --git a/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/flwor-expression.xquery b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/flwor-expression.xquery
new file mode 100644
index 0000000..9ffc5bc
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/flwor-expression.xquery
@@ -0,0 +1,9 @@
+<base>
+{
+	for $item in /items/item
+	let $idname := concat($item/id, $item/name)
+	where $idname != '2second'
+	order by $item/id
+	return $item/id
+}
+</base>
\ No newline at end of file
diff --git a/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/myTransform.xquery b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/myTransform.xquery
new file mode 100644
index 0000000..448fc44
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/myTransform.xquery
@@ -0,0 +1,4 @@
+<employee id="{person/@user}">
+ <name>{/person/firstName} {/person/lastName}</name>
+ <location>{/person/city}</location>
+</employee>
\ No newline at end of file
diff --git a/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/transform.xquery b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/transform.xquery
new file mode 100644
index 0000000..655450e
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/transform.xquery
@@ -0,0 +1,3 @@
+<transformed subject="{mail/subject}">
+{.}
+</transformed>
\ No newline at end of file
diff --git a/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/transformWithExtension.xquery b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/transformWithExtension.xquery
new file mode 100644
index 0000000..dff3ece
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/transformWithExtension.xquery
@@ -0,0 +1,6 @@
+xquery version "1.0" encoding "UTF-8";
+
+(: the prefix declaration for our custom extension :)
+declare namespace efx = "http://test/saxon/ext";
+
+<transformed extension-function-render="{efx:simple(/body/text())}" />
\ No newline at end of file
diff --git a/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/transform_with_headers.xquery b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/transform_with_headers.xquery
new file mode 100644
index 0000000..73a3944
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/transform_with_headers.xquery
@@ -0,0 +1,4 @@
+declare variable $in.headers.foo as xs:string external;
+<transformed sender="{$in.headers.foo}" subject="{mail/subject}">
+{.}
+</transformed>
\ No newline at end of file
diff --git a/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/xqueryExampleTest.xml b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/xqueryExampleTest.xml
new file mode 100644
index 0000000..7ba7278
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/xqueryExampleTest.xml
@@ -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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
+    ">
+
+    <!-- START SNIPPET: example -->
+    <camelContext xmlns="http://camel.apache.org/schema/spring">
+        <route>
+            <from uri="direct:start"/>
+            <to uri="xquery:org/apache/camel/component/xquery/myTransform.xquery"/>
+            <to uri="mock:result"/>
+        </route>
+    </camelContext>
+    <!-- END SNIPPET: example -->
+
+</beans>
diff --git a/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/xqueryWithExplicitTypeContext.xml b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/xqueryWithExplicitTypeContext.xml
new file mode 100644
index 0000000..21d9743
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/resources/org/apache/camel/component/xquery/xqueryWithExplicitTypeContext.xml
@@ -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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
+    ">
+
+  <!-- START SNIPPET: example -->
+  <camelContext xmlns="http://camel.apache.org/schema/spring">
+    <route>
+      <from uri="direct:start"/>
+      <recipientList>
+        <xquery type="java.lang.String">concat('mock:foo.', /person/@city)</xquery>
+      </recipientList>
+    </route>
+  </camelContext>
+  <!-- END SNIPPET: example -->
+
+</beans>
diff --git a/components-starter/camel-saxon-starter/src/test/resources/payload.xml b/components-starter/camel-saxon-starter/src/test/resources/payload.xml
new file mode 100644
index 0000000..9f6abf0
--- /dev/null
+++ b/components-starter/camel-saxon-starter/src/test/resources/payload.xml
@@ -0,0 +1,39 @@
+<?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.
+
+-->
+<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:prox="http://proxy.mycompany.com">
+    <soapenv:Header/>
+    <soapenv:Body>
+        <prox:getServiceFromBus>
+            <serviceName>service1</serviceName>
+            <payload>
+                <inputReportIncident>
+                    <incidentId>01</incidentId>
+                    <incidentDate>2010-10-04</incidentDate>
+                    <givenName>John</givenName>
+                    <familyName>Doe</familyName>
+                    <summary>This is a test report</summary>
+                    <details>server is down</details>
+                    <email>someone@somewhere.com</email>
+                    <phone>12345678</phone>
+                </inputReportIncident>
+            </payload>
+        </prox:getServiceFromBus>
+    </soapenv:Body>
+</soapenv:Envelope>
\ No newline at end of file