You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2023/09/12 06:23:51 UTC

[camel] branch main updated (0c2e3ae8411 -> c64da1bec3b)

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

acosentino pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


    from 0c2e3ae8411 Upgrade JsonApi to version 0.13 (#11364)
     new ee7c4a56118 Initial commit of camel-thymeleaf
     new 4eac38583a3 Initial commit of camel-thymeleaf
     new 93fdb2e32f1 Initial commit of camel-thymeleaf
     new 16152663d95 Working on unit tests
     new 63f9f1f9090 Working on unit tests
     new fcd852ac892 Working on unit tests
     new f87e6c15527 Working on unit tests
     new 117ccb9ad40 Added auto-generated new files and updated files due to new Thymeleaf component
     new 8afe42f713c Fixing PR build errors
     new c64da1bec3b Camel-Thymeleaf: Log for tests only on file

The 10 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 bom/camel-bom/pom.xml                              |   5 +
 catalog/camel-allcomponents/pom.xml                |   5 +
 .../org/apache/camel/catalog/components.properties |   1 +
 .../apache/camel/catalog/components/thymeleaf.json |  49 ++
 components/camel-thymeleaf/pom.xml                 |  91 ++++
 .../thymeleaf/ThymeleafComponentConfigurer.java    |  55 ++
 .../thymeleaf/ThymeleafEndpointConfigurer.java     |  97 ++++
 .../thymeleaf/ThymeleafEndpointUriFactory.java     |  80 +++
 .../services/org/apache/camel/component.properties |   7 +
 .../services/org/apache/camel/component/thymeleaf  |   2 +
 .../apache/camel/configurer/thymeleaf-component    |   2 +
 .../org/apache/camel/configurer/thymeleaf-endpoint |   2 +
 .../org/apache/camel/urifactory/thymeleaf-endpoint |   2 +
 .../camel/component/thymeleaf/thymeleaf.json       |  49 ++
 .../src/main/docs/thymeleaf-component.adoc         | 255 +++++++++
 .../component/thymeleaf/ThymeleafComponent.java    |  41 ++
 .../component/thymeleaf/ThymeleafConstants.java    |  43 ++
 .../component/thymeleaf/ThymeleafEndpoint.java     | 583 +++++++++++++++++++++
 .../component/thymeleaf/ThymeleafResolverType.java |  27 +
 .../camel/component/thymeleaf/FruitFilter.java     |  31 ++
 .../thymeleaf/ThymeleafAbstractBaseTest.java       | 237 +++++++++
 .../thymeleaf/ThymeleafBodyAsDomainObjectTest.java | 133 +++++
 .../ThymeleafClassLoaderResolverAllParamsTest.java | 101 ++++
 .../ThymeleafClassLoaderResolverTest.java          | 101 ++++
 .../thymeleaf/ThymeleafComponentTest.java          | 102 ++++
 .../thymeleaf/ThymeleafConcurrentTest.java         |  79 +++
 .../thymeleaf/ThymeleafContentCacheTest.java       | 227 ++++++++
 .../ThymeleafDefaultResolverAllParamsTest.java     |  96 ++++
 .../thymeleaf/ThymeleafDefaultResolverTest.java    |  96 ++++
 .../component/thymeleaf/ThymeleafEndpointTest.java | 108 ++++
 .../ThymeleafFileResolverAllParamsTest.java        | 100 ++++
 .../thymeleaf/ThymeleafFileResolverTest.java       | 101 ++++
 .../thymeleaf/ThymeleafResourceUriTest.java        |  55 ++
 .../thymeleaf/ThymeleafSetHeaderTest.java          |  59 +++
 .../ThymeleafStringResolverAllParamsTest.java      |  97 ++++
 .../thymeleaf/ThymeleafStringResolverTest.java     |  98 ++++
 .../thymeleaf/ThymeleafTemplateAsHeaderTest.java   |  56 ++
 .../ThymeleafUrlResolverAllParamsTest.java         | 114 ++++
 .../thymeleaf/ThymeleafUrlResolverTest.java        | 114 ++++
 .../thymeleaf/ThymeleafVariableMapHeaderTest.java  |  56 ++
 ...ymeleafWebApplicationResolverAllParamsTest.java | 161 ++++++
 .../ThymeleafWebApplicationResolverTest.java       | 153 ++++++
 .../test/resources/WEB-INF/templates/letter.html   |  24 +
 .../src/test/resources/log4j2.properties           |  29 +
 .../apache/camel/component/thymeleaf/apple.html    |  19 +
 .../camel/component/thymeleaf/camel-context.xml    |  44 ++
 .../camel/component/thymeleaf/concurrent.txt}      |   0
 .../camel/component/thymeleaf/letter-domain.html   |  24 +
 .../apache/camel/component/thymeleaf/letter.html   |  24 +
 .../apache/camel/component/thymeleaf/letter.txt    |  25 +
 .../camel/component/thymeleaf/letterWithUrl.html   |  26 +
 .../apache/camel/component/thymeleaf/orange.html   |  19 +
 components/pom.xml                                 |   1 +
 .../org/apache/camel/main/components.properties    |   1 +
 .../modules/ROOT/examples/json/thymeleaf.json      |   1 +
 docs/components/modules/ROOT/nav.adoc              |   1 +
 .../modules/ROOT/pages/thymeleaf-component.adoc    |   1 +
 .../component/ComponentsBuilderFactory.java        |  13 +
 .../dsl/ThymeleafComponentBuilderFactory.java      | 121 +++++
 .../src/generated/resources/metadata.json          |  22 +
 .../builder/endpoint/EndpointBuilderFactory.java   |   1 +
 .../camel/builder/endpoint/EndpointBuilders.java   |   1 +
 .../builder/endpoint/StaticEndpointBuilders.java   |  55 ++
 .../dsl/ThymeleafEndpointBuilderFactory.java       | 536 +++++++++++++++++++
 .../camel-component-known-dependencies.properties  |   1 +
 parent/pom.xml                                     |   5 +
 66 files changed, 4865 insertions(+)
 create mode 100644 catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/thymeleaf.json
 create mode 100644 components/camel-thymeleaf/pom.xml
 create mode 100644 components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafComponentConfigurer.java
 create mode 100644 components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointConfigurer.java
 create mode 100644 components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointUriFactory.java
 create mode 100644 components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/component.properties
 create mode 100644 components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/component/thymeleaf
 create mode 100644 components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/configurer/thymeleaf-component
 create mode 100644 components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/configurer/thymeleaf-endpoint
 create mode 100644 components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/urifactory/thymeleaf-endpoint
 create mode 100644 components/camel-thymeleaf/src/generated/resources/org/apache/camel/component/thymeleaf/thymeleaf.json
 create mode 100644 components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc
 create mode 100644 components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafComponent.java
 create mode 100644 components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafConstants.java
 create mode 100644 components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafEndpoint.java
 create mode 100644 components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafResolverType.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/FruitFilter.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafAbstractBaseTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafBodyAsDomainObjectTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafClassLoaderResolverAllParamsTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafClassLoaderResolverTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafComponentTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafConcurrentTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafContentCacheTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafDefaultResolverAllParamsTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafDefaultResolverTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafFileResolverAllParamsTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafFileResolverTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafResourceUriTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafSetHeaderTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafStringResolverAllParamsTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafStringResolverTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafTemplateAsHeaderTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafUrlResolverAllParamsTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafUrlResolverTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafVariableMapHeaderTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverAllParamsTest.java
 create mode 100644 components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverTest.java
 create mode 100644 components/camel-thymeleaf/src/test/resources/WEB-INF/templates/letter.html
 create mode 100644 components/camel-thymeleaf/src/test/resources/log4j2.properties
 create mode 100644 components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/apple.html
 create mode 100644 components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/camel-context.xml
 copy components/{camel-freemarker/src/test/resources/org/apache/camel/component/freemarker/Concurrent.ftl => camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/concurrent.txt} (100%)
 create mode 100644 components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter-domain.html
 create mode 100644 components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.html
 create mode 100644 components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.txt
 create mode 100644 components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letterWithUrl.html
 create mode 100644 components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/orange.html
 create mode 120000 docs/components/modules/ROOT/examples/json/thymeleaf.json
 create mode 120000 docs/components/modules/ROOT/pages/thymeleaf-component.adoc
 create mode 100644 dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/ThymeleafComponentBuilderFactory.java
 create mode 100644 dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ThymeleafEndpointBuilderFactory.java


[camel] 02/10: Initial commit of camel-thymeleaf

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 4eac38583a342e8b764879da33ae4e709e663b32
Author: Craig Ziesman <cz...@redhat.com>
AuthorDate: Mon Aug 28 13:18:13 2023 -0500

    Initial commit of camel-thymeleaf
---
 parent/pom.xml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/parent/pom.xml b/parent/pom.xml
index 711243d08d5..7fb27ef9e2b 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -2278,6 +2278,11 @@
                 <artifactId>camel-thrift</artifactId>
                 <version>${project.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.apache.camel</groupId>
+                <artifactId>camel-thymeleaf</artifactId>
+                <version>${project.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.apache.camel</groupId>
                 <artifactId>camel-tika</artifactId>


[camel] 06/10: Working on unit tests

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit fcd852ac89288b292cfd4e50715a16f31d1cc842
Author: Craig Ziesman <cz...@redhat.com>
AuthorDate: Thu Sep 7 13:35:13 2023 -0500

    Working on unit tests
---
 .../component/thymeleaf/ThymeleafEndpoint.java     |   5 +
 .../thymeleaf/ThymeleafAbstractBaseTest.java       |  18 ++--
 .../thymeleaf/ThymeleafBodyAsDomainObjectTest.java |  10 +-
 .../thymeleaf/ThymeleafComponentTest.java          | 101 +++++++++++----------
 .../thymeleaf/ThymeleafConcurrentTest.java         |   6 +-
 .../thymeleaf/ThymeleafContentCacheTest.java       |  13 ++-
 ...ymeleafWebApplicationResolverAllParamsTest.java |   9 +-
 .../ThymeleafWebApplicationResolverTest.java       |   7 +-
 8 files changed, 87 insertions(+), 82 deletions(-)

diff --git a/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafEndpoint.java b/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafEndpoint.java
index f68a9d67a74..833e956e03b 100644
--- a/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafEndpoint.java
+++ b/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafEndpoint.java
@@ -330,6 +330,11 @@ public class ThymeleafEndpoint extends ResourceEndpoint {
         this.jakartaServletWebApplication = jakartaServletWebApplication;
     }
 
+    public void setTemplate(String template) {
+
+        this.template = template;
+    }
+
     @Override
     public void clearContentCache() {
 
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafAbstractBaseTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafAbstractBaseTest.java
index 525a949a8a7..f80064448a9 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafAbstractBaseTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafAbstractBaseTest.java
@@ -16,14 +16,14 @@
  */
 package org.apache.camel.component.thymeleaf;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.test.junit5.CamelTestSupport;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import static java.util.Map.entry;
 
 public abstract class ThymeleafAbstractBaseTest extends CamelTestSupport {
@@ -147,12 +147,12 @@ public abstract class ThymeleafAbstractBaseTest extends CamelTestSupport {
     protected String expected() {
 
         return "\n\n" +
-               "Dear Doe, Jane\n" +
-               "\n" +
-               "Thank you for your order number 7 of Widgets for Dummies.\n" +
-               "\n" +
-               "Regards Camel Riders Bookstore\n" +
-               "Spazz Testing Service";
+                "Dear Doe, Jane\n" +
+                "\n" +
+                "Thank you for your order number 7 of Widgets for Dummies.\n" +
+                "\n" +
+                "Regards Camel Riders Bookstore\n" +
+                "Spazz Testing Service";
     }
 
     @Override
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafBodyAsDomainObjectTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafBodyAsDomainObjectTest.java
index 8dfac7e68b3..b7d6447382b 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafBodyAsDomainObjectTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafBodyAsDomainObjectTest.java
@@ -121,11 +121,11 @@ public class ThymeleafBodyAsDomainObjectTest extends ThymeleafAbstractBaseTest {
         public String toString() {
 
             return "Letter{" +
-                   "firstName='" + firstName + '\'' +
-                   ", lastName='" + lastName + '\'' +
-                   ", item='" + item + '\'' +
-                   ", closing='" + closing + '\'' +
-                   '}';
+                    "firstName='" + firstName + '\'' +
+                    ", lastName='" + lastName + '\'' +
+                    ", item='" + item + '\'' +
+                    ", closing='" + closing + '\'' +
+                    '}';
         }
 
     }
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafComponentTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafComponentTest.java
index a1b403673f7..e2578b165a6 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafComponentTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafComponentTest.java
@@ -16,49 +16,77 @@
  */
 package org.apache.camel.component.thymeleaf;
 
-import java.util.UUID;
-
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.support.PropertyBindingListener;
+import org.apache.camel.test.junit5.CamelTestSupport;
 import org.junit.jupiter.api.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.thymeleaf.templatemode.TemplateMode;
 import org.thymeleaf.templateresolver.ITemplateResolver;
 import org.thymeleaf.templateresolver.StringTemplateResolver;
 
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import static java.util.Map.entry;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.Mockito.spy;
 
-public class ThymeleafComponentTest extends ThymeleafAbstractBaseTest {
-
-    private static final Logger LOG = LoggerFactory.getLogger(ThymeleafComponentTest.class);
+public class ThymeleafComponentTest extends CamelTestSupport {
 
     private String templateMode;
 
-    @Test
-    public void testThymeleaf() throws InterruptedException {
+    protected static String stringTemplate() {
 
-        ThymeleafComponent component = context.getComponent("thymeleaf", ThymeleafComponent.class);
-        assertNotNull(component);
+        return """
+                <!--/*-->
+                    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
 
-        ThymeleafEndpoint thymeleafEndpoint = context.getEndpoint(
-                "thymeleaf:dontcare?templateMode=CSS&allowContextMapAll=true&resolver=STRING",
-                ThymeleafEndpoint.class);
+                         http://www.apache.org/licenses/LICENSE-2.0
 
-        ThymeleafEndpoint spy = spy(thymeleafEndpoint);
-        LOG.info("foo: {}",
-                thymeleafEndpoint.getComponent().getEndpointPropertyConfigurer().getClass());
+                    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.
+                <!--*/-->
+                <!--/* This code will be removed at thymeleaf parsing time! */-->
+                Dear [(${headers.lastName})], [(${headers.firstName})]
 
-        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
-        mock.expectedMessageCount(1);
+                Thank you for your order number [(${exchange.properties.orderNumber})] of [(${headers.item})].
 
-        template.request(DIRECT_START, templateHeaderProcessor);
+                Regards Camel Riders Bookstore
+                [(${body})]""";
+    }
+
+    @Test
+    public void testThymeleaf() throws Exception {
+
+        /*
+         * Listens for the templateMode property binding to allow verification of the <code>createEndpoint()</code>
+         * method in <code>ThymeleafComponent</code>.
+         */
+        context.getRegistry().bind(UUID.randomUUID().toString(),
+                (PropertyBindingListener) (target, key, value) -> {
+                    if ("templateMode".equals(key)) {
+                        templateMode = (String) value;
+                    }
+                });
+
+        ThymeleafComponent component = new ThymeleafComponent();
+        assertNotNull(component);
+        component.setCamelContext(context);
+
+        Map<String, Object> parameters = new HashMap<>(
+                Map.ofEntries(entry("templateMode", "CSS"), entry("allowContextMapAll", true), entry("resolver", "STRING")));
 
-        mock.assertIsSatisfied();
+        ThymeleafEndpoint thymeleafEndpoint = (ThymeleafEndpoint) component.createEndpoint("thymeleaf", "dontcare", parameters);
+        thymeleafEndpoint.setTemplate(stringTemplate());
 
         assertEquals(TemplateMode.CSS.name(), thymeleafEndpoint.getTemplateMode());
 
@@ -71,29 +99,4 @@ public class ThymeleafComponentTest extends ThymeleafAbstractBaseTest {
         assertEquals(TemplateMode.CSS.name(), templateMode);
     }
 
-    @Override
-    protected RouteBuilder createRouteBuilder() {
-
-        return new RouteBuilder() {
-
-            public void configure() {
-
-                from(DIRECT_START)
-                        .setBody(simple(SPAZZ_TESTING_SERVICE))
-                        .to("thymeleaf:dontcare?templateMode=CSS&allowContextMapAll=true&resolver=STRING")
-                        .to(MOCK_RESULT);
-
-                /*
-                 * Listens for the templateMode property binding to allow verification of the <code>createEndpoint()</code>
-                 * method in <code>ThymeleafComponent</code>.
-                 */
-                getCamelContext().getRegistry().bind(UUID.randomUUID().toString(),
-                        (PropertyBindingListener) (target, key, value) -> {
-                            if ("templateMode".equals(key)) {
-                                templateMode = (String) value;
-                            }
-                        });
-            }
-        };
-    }
 }
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafConcurrentTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafConcurrentTest.java
index d38f6796379..220939065d3 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafConcurrentTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafConcurrentTest.java
@@ -16,13 +16,13 @@
  */
 package org.apache.camel.component.thymeleaf;
 
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.junit.jupiter.api.Test;
 
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
 import static org.apache.camel.test.junit5.TestSupport.body;
 
 public class ThymeleafConcurrentTest extends ThymeleafAbstractBaseTest {
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafContentCacheTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafContentCacheTest.java
index 950836a1fa6..42039d7194c 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafContentCacheTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafContentCacheTest.java
@@ -16,13 +16,6 @@
  */
 package org.apache.camel.component.thymeleaf;
 
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-
 import org.apache.camel.Exchange;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
@@ -30,6 +23,12 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.TestInstance;
 
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
 import static java.util.Map.entry;
 
 @TestInstance(TestInstance.Lifecycle.PER_METHOD)
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverAllParamsTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverAllParamsTest.java
index 9be2eeb6179..2c35934fc66 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverAllParamsTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverAllParamsTest.java
@@ -16,12 +16,7 @@
  */
 package org.apache.camel.component.thymeleaf;
 
-import java.io.File;
-import java.io.InputStream;
-import java.net.URL;
-
 import jakarta.servlet.ServletContext;
-
 import org.apache.camel.ExchangePattern;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
@@ -34,6 +29,10 @@ import org.thymeleaf.templateresolver.ITemplateResolver;
 import org.thymeleaf.templateresolver.WebApplicationTemplateResolver;
 import org.thymeleaf.web.servlet.JakartaServletWebApplication;
 
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+
 import static org.junit.jupiter.api.Assertions.assertAll;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverTest.java
index e16270a2962..d75768e8aa0 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverTest.java
@@ -16,11 +16,7 @@
  */
 package org.apache.camel.component.thymeleaf;
 
-import java.io.File;
-import java.io.InputStream;
-
 import jakarta.servlet.ServletContext;
-
 import org.apache.camel.ExchangePattern;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
@@ -33,6 +29,9 @@ import org.thymeleaf.templateresolver.ITemplateResolver;
 import org.thymeleaf.templateresolver.WebApplicationTemplateResolver;
 import org.thymeleaf.web.servlet.JakartaServletWebApplication;
 
+import java.io.File;
+import java.io.InputStream;
+
 import static org.junit.jupiter.api.Assertions.assertAll;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;


[camel] 04/10: Working on unit tests

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 16152663d95ac139bf779094291b97cd3a5dfd0c
Author: Craig Ziesman <cz...@redhat.com>
AuthorDate: Wed Sep 6 19:42:58 2023 -0500

    Working on unit tests
---
 components/camel-thymeleaf/pom.xml                 |  76 ++++-
 .../thymeleaf/ThymeleafComponentConfigurer.java    |  18 --
 .../thymeleaf/ThymeleafEndpointConfigurer.java     |  51 ++--
 .../thymeleaf/ThymeleafEndpointUriFactory.java     |  15 +-
 .../services/org/apache/camel/component.properties |   4 +-
 .../camel/component/thymeleaf/thymeleaf.json       |  33 +--
 .../component/thymeleaf/ThymeleafComponent.java    |  55 ----
 .../component/thymeleaf/ThymeleafConstants.java    |  14 +-
 .../component/thymeleaf/ThymeleafEndpoint.java     |  88 +++---
 .../component/thymeleaf/BruteForceCssTest.java     | 235 ---------------
 .../thymeleaf/BruteForceJavascriptTest.java        | 258 -----------------
 .../camel/component/thymeleaf/BruteForceTest.java  | 317 ---------------------
 .../thymeleaf/BruteForceWebAppResolverTest.java    | 127 ---------
 .../thymeleaf/BruteForceWiremockTest.java          | 107 -------
 .../thymeleaf/ThymeleafAbstractBaseTest.java       | 237 +++++++++++++++
 .../thymeleaf/ThymeleafAttachmentsTest.java        |  76 -----
 .../thymeleaf/ThymeleafBodyAsDomainObjectTest.java |  99 ++++---
 .../ThymeleafClassLoaderResolverAllParamsTest.java | 101 +++++++
 .../ThymeleafClassLoaderResolverTest.java          | 101 +++++++
 .../thymeleaf/ThymeleafComponentTest.java          |  99 +++++++
 .../thymeleaf/ThymeleafConcurrentTest.java         |  24 +-
 .../thymeleaf/ThymeleafContentCacheTest.java       | 160 +++++++----
 .../ThymeleafDefaultResolverAllParamsTest.java     |  96 +++++++
 .../thymeleaf/ThymeleafDefaultResolverTest.java    |  96 +++++++
 .../component/thymeleaf/ThymeleafEndpointTest.java |  78 ++++-
 .../ThymeleafFileResolverAllParamsTest.java        | 101 +++++++
 .../thymeleaf/ThymeleafFileResolverTest.java       | 101 +++++++
 .../ThymeleafLetterWithoutHeaderTest.java          |  36 ---
 .../thymeleaf/ThymeleafOverrideHeaderTest.java     |  97 -------
 ...dingTest.java => ThymeleafResourceUriTest.java} |  25 +-
 .../thymeleaf/ThymeleafSetHeaderTest.java          |  17 +-
 .../ThymeleafStringResolverAllParamsTest.java      |  97 +++++++
 .../thymeleaf/ThymeleafStringResolverTest.java     |  98 +++++++
 ...est.java => ThymeleafTemplateAsHeaderTest.java} |  45 +--
 .../thymeleaf/ThymeleafTemplateInHeaderTest.java   | 100 -------
 .../camel/component/thymeleaf/ThymeleafTest.java   |  92 ------
 .../ThymeleafUrlResolverAllParamsTest.java         | 114 ++++++++
 .../thymeleaf/ThymeleafUrlResolverTest.java        | 114 ++++++++
 .../thymeleaf/ThymeleafValuesInPropertiesTest.java |  70 -----
 ...st.java => ThymeleafVariableMapHeaderTest.java} |  27 +-
 ...ymeleafWebApplicationResolverAllParamsTest.java | 161 +++++++++++
 .../ThymeleafWebApplicationResolverTest.java       | 153 ++++++++++
 .../test/resources/WEB-INF/templates/letter.html   |   6 +-
 .../src/test/resources/log4j2.properties           |   8 +-
 .../camel/component/thymeleaf/OrangeTemplate.txt   |  19 --
 .../{BodyAsDomainObject.txt => apple.html}         |  39 ++-
 .../camel/component/thymeleaf/camel-context.xml    |   8 +-
 .../thymeleaf/{Concurrent.txt => concurrent.txt}   |   0
 .../apache/camel/component/thymeleaf/example.txt   |  19 --
 .../apache/camel/component/thymeleaf/header.txt    |  19 --
 ...{letterWithoutHeader.txt => letter-domain.html} |   8 +-
 .../camel/component/thymeleaf/letter-utf16.txt     | Bin 2166 -> 0 bytes
 .../apache/camel/component/thymeleaf/letter.css    |  40 ---
 .../apache/camel/component/thymeleaf/letter.html   |   6 +-
 .../org/apache/camel/component/thymeleaf/letter.js |  57 ----
 .../apache/camel/component/thymeleaf/letter.txt    |   2 +-
 .../apache/camel/component/thymeleaf/letter.xml    |  34 ---
 .../camel/component/thymeleaf/letterWithUrl.html   |   8 +-
 .../thymeleaf/{AppleTemplate.txt => orange.html}   |   4 +-
 59 files changed, 2213 insertions(+), 2077 deletions(-)

diff --git a/components/camel-thymeleaf/pom.xml b/components/camel-thymeleaf/pom.xml
index 3d2f1d9eca9..736f9e36fb2 100644
--- a/components/camel-thymeleaf/pom.xml
+++ b/components/camel-thymeleaf/pom.xml
@@ -36,6 +36,9 @@
         <thymeleaf-version>3.1.2.RELEASE</thymeleaf-version>
         <jakarta-servlet-api-version>6.0.0</jakarta-servlet-api-version>
         <wiremock-version>3.0.0-beta-15</wiremock-version>
+        <pitest-maven-version>1.14.4</pitest-maven-version>
+        <pitest-junit5-plugin-version>1.2.0</pitest-junit5-plugin-version>
+        <jacoco-maven-plugin-version>0.8.10</jacoco-maven-plugin-version>
     </properties>
 
     <dependencies>
@@ -55,11 +58,6 @@
             <artifactId>camel-test-spring-junit5</artifactId>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>org.apache.camel</groupId>
-            <artifactId>camel-attachments</artifactId>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-management</artifactId>
@@ -90,6 +88,74 @@
             <version>${jakarta-servlet-api-version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-servlet</artifactId>
+            <version>${jetty-version}</version>
+            <scope>test</scope>
+        </dependency>
+
     </dependencies>
 
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <argLine>${argLine}</argLine>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.jacoco</groupId>
+                <artifactId>jacoco-maven-plugin</artifactId>
+                <version>${jacoco-maven-plugin-version}</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>prepare-agent</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>generate-code-coverage-report</id>
+                        <goals>
+                            <goal>report</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <excludes>
+                        <exclude>**/*Configurer.class</exclude>
+                        <exclude>**/*Factory.class</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.pitest</groupId>
+                <artifactId>pitest-maven</artifactId>
+                <version>${pitest-maven-version}</version>
+                <dependencies>
+                    <dependency>
+                        <groupId>org.pitest</groupId>
+                        <artifactId>pitest-junit5-plugin</artifactId>
+                        <version>${pitest-junit5-plugin-version}</version>
+                    </dependency>
+                </dependencies>
+                <configuration>
+                    <targetClasses>
+                        <param>org.apache.camel.component.thymeleaf.*</param>
+                    </targetClasses>
+<!--                    <targetTests>-->
+<!--                        <param>org.apache.camel.component.thymeleaf.*</param>-->
+<!--                    </targetTests>-->
+                    <excludedClasses>
+                        <param>org.apache.camel.component.thymeleaf.*Configurer*</param>
+                        <param>org.apache.camel.component.thymeleaf.*Factory*</param>
+                    </excludedClasses>
+                </configuration>
+            </plugin>
+
+        </plugins>
+    </build>
+
 </project>
diff --git a/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafComponentConfigurer.java b/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafComponentConfigurer.java
index 09f9259f230..2830cb64c2a 100644
--- a/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafComponentConfigurer.java
+++ b/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafComponentConfigurer.java
@@ -21,16 +21,10 @@ public class ThymeleafComponentConfigurer extends PropertyConfigurerSupport impl
     public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
         ThymeleafComponent target = (ThymeleafComponent) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
-        case "allowcontextmapall":
-        case "allowContextMapAll": target.setAllowContextMapAll(property(camelContext, boolean.class, value)); return true;
-        case "allowtemplatefromheader":
-        case "allowTemplateFromHeader": target.setAllowTemplateFromHeader(property(camelContext, boolean.class, value)); return true;
         case "autowiredenabled":
         case "autowiredEnabled": target.setAutowiredEnabled(property(camelContext, boolean.class, value)); return true;
         case "lazystartproducer":
         case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
-        case "templateengine":
-        case "templateEngine": target.setTemplateEngine(property(camelContext, org.thymeleaf.TemplateEngine.class, value)); return true;
         default: return false;
         }
     }
@@ -38,16 +32,10 @@ public class ThymeleafComponentConfigurer extends PropertyConfigurerSupport impl
     @Override
     public Class<?> getOptionType(String name, boolean ignoreCase) {
         switch (ignoreCase ? name.toLowerCase() : name) {
-        case "allowcontextmapall":
-        case "allowContextMapAll": return boolean.class;
-        case "allowtemplatefromheader":
-        case "allowTemplateFromHeader": return boolean.class;
         case "autowiredenabled":
         case "autowiredEnabled": return boolean.class;
         case "lazystartproducer":
         case "lazyStartProducer": return boolean.class;
-        case "templateengine":
-        case "templateEngine": return org.thymeleaf.TemplateEngine.class;
         default: return null;
         }
     }
@@ -56,16 +44,10 @@ public class ThymeleafComponentConfigurer extends PropertyConfigurerSupport impl
     public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
         ThymeleafComponent target = (ThymeleafComponent) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
-        case "allowcontextmapall":
-        case "allowContextMapAll": return target.isAllowContextMapAll();
-        case "allowtemplatefromheader":
-        case "allowTemplateFromHeader": return target.isAllowTemplateFromHeader();
         case "autowiredenabled":
         case "autowiredEnabled": return target.isAutowiredEnabled();
         case "lazystartproducer":
         case "lazyStartProducer": return target.isLazyStartProducer();
-        case "templateengine":
-        case "templateEngine": return target.getTemplateEngine();
         default: return null;
         }
     }
diff --git a/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointConfigurer.java b/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointConfigurer.java
index 8aee40302f9..c6ee09ec001 100644
--- a/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointConfigurer.java
+++ b/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointConfigurer.java
@@ -23,17 +23,22 @@ public class ThymeleafEndpointConfigurer extends PropertyConfigurerSupport imple
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "allowcontextmapall":
         case "allowContextMapAll": target.setAllowContextMapAll(property(camelContext, boolean.class, value)); return true;
-        case "allowtemplatefromheader":
-        case "allowTemplateFromHeader": target.setAllowTemplateFromHeader(property(camelContext, boolean.class, value)); return true;
+        case "cachetimetolive":
+        case "cacheTimeToLive": target.setCacheTimeToLive(property(camelContext, java.lang.Long.class, value)); return true;
+        case "cacheable": target.setCacheable(property(camelContext, java.lang.Boolean.class, value)); return true;
+        case "checkexistence":
+        case "checkExistence": target.setCheckExistence(property(camelContext, java.lang.Boolean.class, value)); return true;
         case "contentcache":
         case "contentCache": target.setContentCache(property(camelContext, boolean.class, value)); return true;
         case "encoding": target.setEncoding(property(camelContext, java.lang.String.class, value)); return true;
         case "lazystartproducer":
         case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
-        case "loadercache":
-        case "loaderCache": target.setLoaderCache(property(camelContext, boolean.class, value)); return true;
-        case "propertiesfile":
-        case "propertiesFile": target.setPropertiesFile(property(camelContext, java.lang.String.class, value)); return true;
+        case "order": target.setOrder(property(camelContext, java.lang.Integer.class, value)); return true;
+        case "prefix": target.setPrefix(property(camelContext, java.lang.String.class, value)); return true;
+        case "resolver": target.setResolver(property(camelContext, org.apache.camel.component.thymeleaf.ThymeleafResolverType.class, value)); return true;
+        case "suffix": target.setSuffix(property(camelContext, java.lang.String.class, value)); return true;
+        case "templatemode":
+        case "templateMode": target.setTemplateMode(property(camelContext, java.lang.String.class, value)); return true;
         default: return false;
         }
     }
@@ -43,17 +48,22 @@ public class ThymeleafEndpointConfigurer extends PropertyConfigurerSupport imple
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "allowcontextmapall":
         case "allowContextMapAll": return boolean.class;
-        case "allowtemplatefromheader":
-        case "allowTemplateFromHeader": return boolean.class;
+        case "cachetimetolive":
+        case "cacheTimeToLive": return java.lang.Long.class;
+        case "cacheable": return java.lang.Boolean.class;
+        case "checkexistence":
+        case "checkExistence": return java.lang.Boolean.class;
         case "contentcache":
         case "contentCache": return boolean.class;
         case "encoding": return java.lang.String.class;
         case "lazystartproducer":
         case "lazyStartProducer": return boolean.class;
-        case "loadercache":
-        case "loaderCache": return boolean.class;
-        case "propertiesfile":
-        case "propertiesFile": return java.lang.String.class;
+        case "order": return java.lang.Integer.class;
+        case "prefix": return java.lang.String.class;
+        case "resolver": return org.apache.camel.component.thymeleaf.ThymeleafResolverType.class;
+        case "suffix": return java.lang.String.class;
+        case "templatemode":
+        case "templateMode": return java.lang.String.class;
         default: return null;
         }
     }
@@ -64,17 +74,22 @@ public class ThymeleafEndpointConfigurer extends PropertyConfigurerSupport imple
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "allowcontextmapall":
         case "allowContextMapAll": return target.isAllowContextMapAll();
-        case "allowtemplatefromheader":
-        case "allowTemplateFromHeader": return target.isAllowTemplateFromHeader();
+        case "cachetimetolive":
+        case "cacheTimeToLive": return target.getCacheTimeToLive();
+        case "cacheable": return target.getCacheable();
+        case "checkexistence":
+        case "checkExistence": return target.getCheckExistence();
         case "contentcache":
         case "contentCache": return target.isContentCache();
         case "encoding": return target.getEncoding();
         case "lazystartproducer":
         case "lazyStartProducer": return target.isLazyStartProducer();
-        case "loadercache":
-        case "loaderCache": return target.isLoaderCache();
-        case "propertiesfile":
-        case "propertiesFile": return target.getPropertiesFile();
+        case "order": return target.getOrder();
+        case "prefix": return target.getPrefix();
+        case "resolver": return target.getResolver();
+        case "suffix": return target.getSuffix();
+        case "templatemode":
+        case "templateMode": return target.getTemplateMode();
         default: return null;
         }
     }
diff --git a/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointUriFactory.java b/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointUriFactory.java
index 8d767397c70..9aeee842ada 100644
--- a/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointUriFactory.java
+++ b/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointUriFactory.java
@@ -15,21 +15,26 @@ import org.apache.camel.spi.EndpointUriFactory;
  */
 public class ThymeleafEndpointUriFactory extends org.apache.camel.support.component.EndpointUriFactorySupport implements EndpointUriFactory {
 
-    private static final String BASE = ":resourceUri";
+    private static final String BASE = ":templatePath";
 
     private static final Set<String> PROPERTY_NAMES;
     private static final Set<String> SECRET_PROPERTY_NAMES;
     private static final Set<String> MULTI_VALUE_PREFIXES;
     static {
-        Set<String> props = new HashSet<>(8);
+        Set<String> props = new HashSet<>(13);
         props.add("allowContextMapAll");
-        props.add("allowTemplateFromHeader");
+        props.add("cacheTimeToLive");
+        props.add("cacheable");
+        props.add("checkExistence");
         props.add("contentCache");
         props.add("encoding");
         props.add("lazyStartProducer");
-        props.add("loaderCache");
-        props.add("propertiesFile");
+        props.add("order");
+        props.add("prefix");
+        props.add("resolver");
         props.add("resourceUri");
+        props.add("suffix");
+        props.add("templateMode");
         PROPERTY_NAMES = Collections.unmodifiableSet(props);
         SECRET_PROPERTY_NAMES = Collections.emptySet();
         MULTI_VALUE_PREFIXES = Collections.emptySet();
diff --git a/components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/component.properties b/components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/component.properties
index 4429c6a0412..c9c73e47de3 100644
--- a/components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/component.properties
+++ b/components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/component.properties
@@ -2,6 +2,6 @@
 components=thymeleaf
 groupId=org.apache.camel
 artifactId=camel-thymeleaf
-version=4.0.0-SNAPSHOT
-projectName=Camel :: thymeleaf
+version=4.1.0-SNAPSHOT
+projectName=Camel :: Thymeleaf
 projectDescription=Camel Thymeleaf support
diff --git a/components/camel-thymeleaf/src/generated/resources/org/apache/camel/component/thymeleaf/thymeleaf.json b/components/camel-thymeleaf/src/generated/resources/org/apache/camel/component/thymeleaf/thymeleaf.json
index 4fb1119fe95..07f99ce1ed7 100644
--- a/components/camel-thymeleaf/src/generated/resources/org/apache/camel/component/thymeleaf/thymeleaf.json
+++ b/components/camel-thymeleaf/src/generated/resources/org/apache/camel/component/thymeleaf/thymeleaf.json
@@ -11,10 +11,10 @@
     "supportLevel": "Stable",
     "groupId": "org.apache.camel",
     "artifactId": "camel-thymeleaf",
-    "version": "4.0.0-SNAPSHOT",
+    "version": "4.1.0-SNAPSHOT",
     "scheme": "thymeleaf",
     "extendsScheme": "",
-    "syntax": "thymeleaf:resourceUri",
+    "syntax": "thymeleaf:templatePath",
     "async": false,
     "api": false,
     "consumerOnly": false,
@@ -22,27 +22,28 @@
     "lenientProperties": false
   },
   "componentProperties": {
-    "allowContextMapAll": { "index": 0, "kind": "property", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and Ca [...]
-    "allowTemplateFromHeader": { "index": 1, "kind": "property", "displayName": "Allow Template From Header", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to allow to use resource template from header or not (default false). Enabling this allows to specify dynamic templates via message header. However this can be seen as a potential se [...]
-    "lazyStartProducer": { "index": 2, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
-    "autowiredEnabled": { "index": 3, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...]
-    "templateEngine": { "index": 4, "kind": "property", "displayName": "Template Engine", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.thymeleaf.TemplateEngine", "deprecated": false, "autowired": false, "secret": false, "description": "To use the TemplateEngine otherwise a new engine is created" }
+    "lazyStartProducer": { "index": 0, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
+    "autowiredEnabled": { "index": 1, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...]
   },
   "headers": {
     "CamelThymeleafResourceUri": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of the Thymeleaf template.", "constantName": "org.apache.camel.component.thymeleaf.ThymeleafConstants#THYMELEAF_RESOURCE_URI" },
     "CamelThymeleafTemplate": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The content of the Thymeleaf template.", "constantName": "org.apache.camel.component.thymeleaf.ThymeleafConstants#THYMELEAF_TEMPLATE" },
-    "CamelThymeleafContext": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "org.thymeleaf.context.Context", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Thymeleaf context to use.", "constantName": "org.apache.camel.component.thymeleaf.ThymeleafConstants#THYMELEAF_CONTEXT" },
-    "CamelThymeleafLocale": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "java.util.Locale", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The locale of the Thymeleaf context.", "constantName": "org.apache.camel.component.thymeleaf.ThymeleafConstants#THYMELEAF_LOCALE" },
-    "CamelThymeleafVariableMap": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Map<String, Object>", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "To add additional information to the used ThymeleafContext. The value of this header should be a Map with key\/values that will added (override any existing key with the same name). This can be used to pre setup some common [...]
+    "CamelThymeleafVariableMap": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Map<String, Object>", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The value of this header should be a Map with key\/values that will be override any existing key with the same name. This can be used to preconfigure common key\/values you want to reuse in your Thymeleaf endpoints.", "cons [...]
+    "CamelThymeleafServletContext": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "jakarta.servlet.ServletContext", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The ServletContext for a web application.", "constantName": "org.apache.camel.component.thymeleaf.ThymeleafConstants#THYMELEAF_SERVLET_CONTEXT" }
   },
   "properties": {
     "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will look [...]
     "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and C [...]
-    "allowTemplateFromHeader": { "index": 2, "kind": "parameter", "displayName": "Allow Template From Header", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to allow to use resource template from header or not (default false). Enabling this allows to specify dynamic templates via message header. However this can be seen as a potential s [...]
-    "contentCache": { "index": 3, "kind": "parameter", "displayName": "Content Cache", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether to use resource content cache or not" },
-    "encoding": { "index": 4, "kind": "parameter", "displayName": "Encoding", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Character encoding of the resource content." },
-    "loaderCache": { "index": 5, "kind": "parameter", "displayName": "Loader Cache", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Enables \/ disables the thymeleaf resource loader cache which is enabled by default" },
-    "propertiesFile": { "index": 6, "kind": "parameter", "displayName": "Properties File", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The URI of the properties file which is used for TemplateEngine initialization." },
-    "lazyStartProducer": { "index": 7, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produc [...]
+    "cacheable": { "index": 2, "kind": "parameter", "displayName": "Cacheable", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "description": "Whether templates have to be considered cacheable or not." },
+    "cacheTimeToLive": { "index": 3, "kind": "parameter", "displayName": "Cache Time To Live", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "description": "The cache Time To Live for templates, expressed in milliseconds." },
+    "checkExistence": { "index": 4, "kind": "parameter", "displayName": "Check Existence", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "description": "Whether a template resources will be checked for existence before being returned." },
+    "contentCache": { "index": 5, "kind": "parameter", "displayName": "Content Cache", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether to use resource content cache or not" },
+    "encoding": { "index": 6, "kind": "parameter", "displayName": "Encoding", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The character encoding to be used for reading template resources." },
+    "order": { "index": 7, "kind": "parameter", "displayName": "Order", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "description": "The order in which this template will be resolved as part of the resolver chain." },
+    "prefix": { "index": 8, "kind": "parameter", "displayName": "Prefix", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "An optional prefix added to template names to convert them into resource names." },
+    "resolver": { "index": 9, "kind": "parameter", "displayName": "Resolver", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.thymeleaf.ThymeleafResolverType", "enum": [ "CLASS_LOADER", "DEFAULT", "FILE", "STRING", "URL", "WEB_APP" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "CLASS_LOADER", "description": "The type of resolver to be used by the template engine." },
+    "suffix": { "index": 10, "kind": "parameter", "displayName": "Suffix", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "An optional suffix added to template names to convert them into resource names." },
+    "templateMode": { "index": 11, "kind": "parameter", "displayName": "Template Mode", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The template mode to be applied to templates." },
+    "lazyStartProducer": { "index": 12, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
   }
 }
diff --git a/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafComponent.java b/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafComponent.java
index 20be6854ecc..014a21e0d57 100644
--- a/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafComponent.java
+++ b/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafComponent.java
@@ -19,71 +19,16 @@ package org.apache.camel.component.thymeleaf;
 import java.util.Map;
 
 import org.apache.camel.Endpoint;
-import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.annotations.Component;
 import org.apache.camel.support.DefaultComponent;
-import org.thymeleaf.TemplateEngine;
 
 @Component("thymeleaf")
 public class ThymeleafComponent extends DefaultComponent {
 
-    //    @Metadata(defaultValue = "false")
-    //    private boolean allowTemplateFromHeader;
-
-    @Metadata(defaultValue = "false")
-    private boolean allowContextMapAll;
-
-    @Metadata(label = "advanced")
-    private TemplateEngine templateEngine;
-
     public ThymeleafComponent() {
 
     }
 
-    public TemplateEngine getTemplateEngine() {
-
-        return templateEngine;
-    }
-
-    /**
-     * To use the {@link TemplateEngine} otherwise a new engine is created
-     */
-    public void setTemplateEngine(TemplateEngine templateEngine) {
-
-        this.templateEngine = templateEngine;
-    }
-
-    //    public boolean isAllowTemplateFromHeader() {
-    //
-    //        return allowTemplateFromHeader;
-    //    }
-
-    /**
-     * Whether to allow to use resource template from header or not (default false).
-     * <p>
-     * Enabling this allows to specify dynamic templates via message header. However, this can be seen as a potential
-     * security vulnerability if the header is coming from a malicious user, so use this with care.
-     */
-    //    public void setAllowTemplateFromHeader(boolean allowTemplateFromHeader) {
-    //
-    //        this.allowTemplateFromHeader = allowTemplateFromHeader;
-    //    }
-
-    public boolean isAllowContextMapAll() {
-
-        return allowContextMapAll;
-    }
-
-    /**
-     * Sets whether the context map should allow access to all details. By default, only the message body and headers
-     * can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so
-     * impose a potential security risk as this opens access to the full power of CamelContext API.
-     */
-    public void setAllowContextMapAll(boolean allowContextMapAll) {
-
-        this.allowContextMapAll = allowContextMapAll;
-    }
-
     @Override
     protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
 
diff --git a/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafConstants.java b/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafConstants.java
index 4da163357f9..796db9ca9bf 100644
--- a/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafConstants.java
+++ b/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafConstants.java
@@ -26,20 +26,16 @@ public class ThymeleafConstants {
     @Metadata(description = "The content of the Thymeleaf template.", javaType = "String")
     public static final String THYMELEAF_TEMPLATE = "CamelThymeleafTemplate";
 
-    @Metadata(description = "The Thymeleaf context to use.", javaType = "org.thymeleaf.context.Context")
-    public static final String THYMELEAF_CONTEXT = "CamelThymeleafContext";
-
-    @Metadata(description = "The locale of the Thymeleaf context.", javaType = "java.util.Locale")
-    public static final String THYMELEAF_LOCALE = "CamelThymeleafLocale";
-
-    @Metadata(description = "To add additional information to the used ThymeleafContext.\n" +
-                            "The value of this header should be a `Map` with key/values that will be\n" +
-                            "added and override any existing key with the same name. \n" +
+    @Metadata(description = "The value of this header should be a `Map` with key/values that will be\n" +
+                            "override any existing key with the same name. \n" +
                             "This can be used to preconfigure common key/values you want to reuse\n" +
                             "in your Thymeleaf endpoints.",
               javaType = "Map<String, Object>")
     public static final String THYMELEAF_VARIABLE_MAP = "CamelThymeleafVariableMap";
 
+    @Metadata(description = "The ServletContext for a web application.", javaType = "jakarta.servlet.ServletContext")
+    public static final String THYMELEAF_SERVLET_CONTEXT = "CamelThymeleafServletContext";
+
     private ThymeleafConstants() {
 
     }
diff --git a/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafEndpoint.java b/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafEndpoint.java
index e2ce9eced17..f68a9d67a74 100644
--- a/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafEndpoint.java
+++ b/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafEndpoint.java
@@ -30,7 +30,6 @@ import org.apache.camel.support.ExchangeHelper;
 import org.apache.camel.util.ObjectHelper;
 import org.thymeleaf.TemplateEngine;
 import org.thymeleaf.context.Context;
-import org.thymeleaf.templatemode.TemplateMode;
 import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
 import org.thymeleaf.templateresolver.DefaultTemplateResolver;
 import org.thymeleaf.templateresolver.FileTemplateResolver;
@@ -38,45 +37,47 @@ import org.thymeleaf.templateresolver.ITemplateResolver;
 import org.thymeleaf.templateresolver.StringTemplateResolver;
 import org.thymeleaf.templateresolver.UrlTemplateResolver;
 import org.thymeleaf.templateresolver.WebApplicationTemplateResolver;
+import org.thymeleaf.web.servlet.JakartaServletWebApplication;
 
 /**
  * Transform messages using a Thymeleaf template.
  */
-@UriEndpoint(firstVersion = "1.0.0", scheme = "thymeleaf", title = "Thymeleaf", syntax = "thymeleaf:resourceUri",
+@UriEndpoint(firstVersion = "1.0.0", scheme = "thymeleaf", title = "Thymeleaf", syntax = "thymeleaf:templatePath",
              producerOnly = true, category = { Category.TRANSFORMATION }, headersClass = ThymeleafConstants.class)
 public class ThymeleafEndpoint extends ResourceEndpoint {
 
     private TemplateEngine templateEngine;
 
+    private String template;
+
+    private JakartaServletWebApplication jakartaServletWebApplication;
+
     @UriParam(defaultValue = "CLASS_LOADER", description = "The type of resolver to be used by the template engine.",
               javaType = "org.apache.camel.component.thymeleaf.ThymeleafResolverType")
     private ThymeleafResolverType resolver = ThymeleafResolverType.CLASS_LOADER;
 
-    @UriParam
+    @UriParam(description = "The template mode to be applied to templates.")
     private String templateMode;
 
-    @UriParam
+    @UriParam(description = "An optional prefix added to template names to convert them into resource names.")
     private String prefix;
 
-    @UriParam
+    @UriParam(description = "An optional suffix added to template names to convert them into resource names.")
     private String suffix;
 
-    @UriParam
-    private String template;
-
-    @UriParam
+    @UriParam(description = "The character encoding to be used for reading template resources.")
     private String encoding;
 
-    @UriParam
+    @UriParam(description = "The order in which this template will be resolved as part of the resolver chain.")
     private Integer order;
 
-    @UriParam
+    @UriParam(description = "Whether a template resources will be checked for existence before being returned.")
     private Boolean checkExistence;
 
-    @UriParam
+    @UriParam(description = "The cache Time To Live for templates, expressed in milliseconds.")
     private Long cacheTimeToLive;
 
-    @UriParam
+    @UriParam(description = "Whether templates have to be considered cacheable or not.")
     private Boolean cacheable;
 
     public ThymeleafEndpoint() {
@@ -100,19 +101,8 @@ public class ThymeleafEndpoint extends ResourceEndpoint {
         return "thymeleaf:" + getResourceUri();
     }
 
-    public String getTemplate() {
-
-        return template;
-    }
-
-    public void setTemplate(String template) {
-
-        this.template = template;
-    }
-
     public String getTemplateMode() {
 
-        TemplateMode f;
         return templateMode;
     }
 
@@ -227,7 +217,7 @@ public class ThymeleafEndpoint extends ResourceEndpoint {
         this.order = order;
     }
 
-    public Boolean isCheckExistence() {
+    public Boolean getCheckExistence() {
 
         return checkExistence;
     }
@@ -268,7 +258,7 @@ public class ThymeleafEndpoint extends ResourceEndpoint {
         this.cacheTimeToLive = cacheTimeToLive;
     }
 
-    public Boolean isCacheable() {
+    public Boolean getCacheable() {
 
         return cacheable;
     }
@@ -285,7 +275,7 @@ public class ThymeleafEndpoint extends ResourceEndpoint {
         this.cacheable = cacheable;
     }
 
-    private synchronized TemplateEngine getTemplateEngine() {
+    protected synchronized TemplateEngine getTemplateEngine() {
 
         if (templateEngine == null) {
             ITemplateResolver templateResolver;
@@ -335,6 +325,19 @@ public class ThymeleafEndpoint extends ResourceEndpoint {
         this.templateEngine = templateEngine;
     }
 
+    public void setJakartaServletWebApplication(JakartaServletWebApplication jakartaServletWebApplication) {
+
+        this.jakartaServletWebApplication = jakartaServletWebApplication;
+    }
+
+    @Override
+    public void clearContentCache() {
+
+        if (templateEngine != null) {
+            templateEngine.clearTemplateCache();
+        }
+    }
+
     public ThymeleafEndpoint findOrCreateEndpoint(String uri, String newResourceUri) {
 
         String newUri = uri.replace(getResourceUri(), newResourceUri);
@@ -350,40 +353,45 @@ public class ThymeleafEndpoint extends ResourceEndpoint {
 
         String newResourceUri = exchange.getIn().getHeader(ThymeleafConstants.THYMELEAF_RESOURCE_URI, String.class);
         if (newResourceUri != null) {
-            // remove the header to avoid it being propagated in the routing
+            // remove the header so that it is not propagated in the exchange
             exchange.getIn().removeHeader(ThymeleafConstants.THYMELEAF_RESOURCE_URI);
 
-            log.debug("{} set to {} creating new endpoint to handle exchange",
+            log.debug("{} set to {}, creating new endpoint to handle exchange",
                     ThymeleafConstants.THYMELEAF_RESOURCE_URI, newResourceUri);
-            ThymeleafEndpoint newEndpoint = findOrCreateEndpoint(getEndpointUri(), newResourceUri);
-            newEndpoint.onExchange(exchange);
+            try (ThymeleafEndpoint newEndpoint = findOrCreateEndpoint(getEndpointUri(), newResourceUri)) {
+                newEndpoint.onExchange(exchange);
+            }
 
             return;
         }
 
         String template = exchange.getIn().getHeader(ThymeleafConstants.THYMELEAF_TEMPLATE, String.class);
         if (template != null) {
-            // remove the header to avoid it being propagated in the routing
+            this.template = template;
+            // remove the header so that it is not propagated in the exchange
             exchange.getIn().removeHeader(ThymeleafConstants.THYMELEAF_TEMPLATE);
+        } else {
+            this.template = path;
         }
 
+        @SuppressWarnings("unchecked")
         Map<String, Object> dataModel = exchange.getIn().getHeader(ThymeleafConstants.THYMELEAF_VARIABLE_MAP, Map.class);
         if (dataModel == null) {
             dataModel = ExchangeHelper.createVariableMap(exchange, isAllowContextMapAll());
         } else {
-            // remove the header to avoid it being propagated in the routing
+            ExchangeHelper.populateVariableMap(exchange, dataModel, isAllowContextMapAll());
+
+            // remove the header so that it is not propagated in the exchange
             exchange.getIn().removeHeader(ThymeleafConstants.THYMELEAF_VARIABLE_MAP);
         }
 
         // let thymeleaf parse and generate the result
         TemplateEngine templateEngine = getTemplateEngine();
-
         Context context = new Context();
         context.setVariables(dataModel);
+        String buffer = templateEngine.process(this.template, context);
 
-        String buffer = templateEngine.process(template, context);
-
-        // now store the result in the exchange body
+        // store the result in the exchange body
         ExchangeHelper.setInOutBodyPatternAware(exchange, buffer);
     }
 
@@ -513,9 +521,6 @@ public class ThymeleafEndpoint extends ResourceEndpoint {
         if (encoding != null) {
             resolver.setCharacterEncoding(encoding);
         }
-        if (checkExistence != null) {
-            resolver.setCheckExistence(checkExistence);
-        }
         if (order != null) {
             resolver.setOrder(order);
         }
@@ -537,7 +542,8 @@ public class ThymeleafEndpoint extends ResourceEndpoint {
 
     private ITemplateResolver webApplicationTemplateResolver() {
 
-        WebApplicationTemplateResolver resolver = new WebApplicationTemplateResolver(null);
+        WebApplicationTemplateResolver resolver = new WebApplicationTemplateResolver(jakartaServletWebApplication);
+
         if (cacheable != null) {
             resolver.setCacheable(cacheable);
         }
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceCssTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceCssTest.java
deleted file mode 100644
index b3ea17f9135..00000000000
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceCssTest.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.thymeleaf;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.jupiter.api.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.thymeleaf.TemplateEngine;
-import org.thymeleaf.context.Context;
-import org.thymeleaf.templatemode.TemplateMode;
-import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
-import org.thymeleaf.templateresolver.DefaultTemplateResolver;
-import org.thymeleaf.templateresolver.StringTemplateResolver;
-
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-public class BruteForceCssTest {
-
-    private static final String TEMPLATE_NAME = "letter";
-
-    private static final Logger LOG = LoggerFactory.getLogger(BruteForceCssTest.class);
-
-    @Test
-    public void testClassLoaderTemplateResolverCss() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.CSS);
-        resolver.setCharacterEncoding("UTF-8");
-        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
-        resolver.setSuffix(".css");
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testClassLoaderTemplateResolverTxt() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.TEXT);
-        resolver.setCharacterEncoding("UTF-8");
-        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
-        resolver.setSuffix(".css");
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testClassLoaderTemplateResolverHtml() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.HTML);
-        resolver.setCharacterEncoding("UTF-8");
-        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
-        resolver.setSuffix(".css");
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testDefaultTemplateResolverCss() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        DefaultTemplateResolver resolver = new DefaultTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.CSS);
-        resolver.setTemplate(cssTemplate());
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testDefaultTemplateResolverTxt() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        DefaultTemplateResolver resolver = new DefaultTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.TEXT);
-        resolver.setTemplate(cssTemplate());
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testDefaultTemplateResolverHtml() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        DefaultTemplateResolver resolver = new DefaultTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.HTML);
-        resolver.setTemplate(cssTemplate());
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testStringTemplateResolverCss() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        StringTemplateResolver resolver = new StringTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.CSS);
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(cssTemplate(), context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testStringTemplateResolverTxt() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        StringTemplateResolver resolver = new StringTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.TEXT);
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(cssTemplate(), context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testStringTemplateResolverHtml() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        StringTemplateResolver resolver = new StringTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.HTML);
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(cssTemplate(), context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    protected Context context() {
-
-        Context context = new Context();
-        context.setVariable("headers", headers());
-
-        return context;
-    }
-
-    protected Map<String, Object> headers() {
-
-        Map<String, Object> headers = new HashMap<>();
-        headers.put("display", "block");
-        headers.put("height", "5.6em");
-
-        return headers;
-    }
-
-    protected String cssTemplate() {
-
-        return """
-                <!--/*
-                    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.
-
-                    Comments are not supported in CSS templates, so this ASF header will appear in the rendered text.
-                */-->
-                # just a comment
-                .fixed_header tbody {
-                    display: /*[(${headers.display})]*/ inline;
-                    overflow: auto;
-                    height: /*[(${headers.height})]*/ 1.0em;
-                }
-                """;
-    }
-
-}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceJavascriptTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceJavascriptTest.java
deleted file mode 100644
index 47ceec2a8f0..00000000000
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceJavascriptTest.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.thymeleaf;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.jupiter.api.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.thymeleaf.TemplateEngine;
-import org.thymeleaf.context.Context;
-import org.thymeleaf.templatemode.TemplateMode;
-import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
-import org.thymeleaf.templateresolver.DefaultTemplateResolver;
-import org.thymeleaf.templateresolver.StringTemplateResolver;
-
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-public class BruteForceJavascriptTest {
-
-    private static final String TEMPLATE_NAME = "letter";
-
-    private static final Logger LOG = LoggerFactory.getLogger(BruteForceJavascriptTest.class);
-
-    @Test
-    public void testClassLoaderTemplateResolverJavascript() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.JAVASCRIPT);
-        resolver.setCharacterEncoding("UTF-8");
-        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
-        resolver.setSuffix(".js");
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testClassLoaderTemplateResolverTxt() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.TEXT);
-        resolver.setCharacterEncoding("UTF-8");
-        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
-        resolver.setSuffix(".js");
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testClassLoaderTemplateResolverHtml() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.HTML);
-        resolver.setCharacterEncoding("UTF-8");
-        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
-        resolver.setSuffix(".js");
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testDefaultTemplateResolverJavascript() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        DefaultTemplateResolver resolver = new DefaultTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.JAVASCRIPT);
-        resolver.setTemplate(jsTemplate());
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testDefaultTemplateResolverTxt() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        DefaultTemplateResolver resolver = new DefaultTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.TEXT);
-        resolver.setTemplate(jsTemplate());
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testDefaultTemplateResolverHtml() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        DefaultTemplateResolver resolver = new DefaultTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.HTML);
-        resolver.setTemplate(jsTemplate());
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testStringTemplateResolverJavascript() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        StringTemplateResolver resolver = new StringTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.JAVASCRIPT);
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(jsTemplate(), context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testStringTemplateResolverTxt() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        StringTemplateResolver resolver = new StringTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.TEXT);
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(jsTemplate(), context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testStringTemplateResolverHtml() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        StringTemplateResolver resolver = new StringTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.HTML);
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(jsTemplate(), context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    protected Context context() {
-
-        Context context = new Context();
-        context.setVariable("headers", headers());
-        context.setVariable("body", body());
-
-        return context;
-    }
-
-    protected Map<String, Object> headers() {
-
-        Map<String, Object> headers = new HashMap<>();
-        headers.put("showContentButton", "testShowContentButton");
-        headers.put("hideContentButton", "testHideContentButton");
-
-        return headers;
-    }
-
-    protected Object body() {
-
-        return "testSomeContent";
-    }
-
-    protected String jsTemplate() {
-
-        return """
-                <!--/*
-                    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.
-
-                    Comments are not supported in JAVASCRIPT templates, so this ASF header will appear in the rendered text.
-                */-->
-                <span th:fragment="show-hide-content" th:remove="tag">
-                    <script th:inline="javascript">
-                        function hideContent() {
-                            showContentButton = document.getElementById(/*[[${headers.showContentButton}]]*/ 'showContentButton');
-                            hideContentButton = document.getElementById(/*[[${headers.hideContentButton}]]*/ 'hideContentButton');
-                            someContent = document.getElementById(/*[[${body}]]*/ 'someContent');
-
-                            showContentButton.style.display = 'block';
-                            hideContentButton.style.display = 'none';
-                            someContent.style.display = 'none';
-                        }
-
-                        function showContent() {
-                            showContentButton = document.getElementById(/*[[${headers.showContentButton}]]*/ 'showContentButton');
-                            hideContentButton = document.getElementById(/*[[${headers.hideContentButton}]]*/ 'hideContentButton');
-                            someContent = document.getElementById(/*[[${body}]]*/ 'someContent');
-
-                            showContentButton.style.display = 'none';
-                            hideContentButton.style.display = 'block';
-                            someContent.style.display = 'block';
-                        }
-                    </script>
-                </span>
-                """;
-    }
-
-}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceTest.java
deleted file mode 100644
index 192677671bf..00000000000
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceTest.java
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.thymeleaf;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.jupiter.api.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.thymeleaf.TemplateEngine;
-import org.thymeleaf.context.Context;
-import org.thymeleaf.templatemode.TemplateMode;
-import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
-import org.thymeleaf.templateresolver.DefaultTemplateResolver;
-import org.thymeleaf.templateresolver.FileTemplateResolver;
-import org.thymeleaf.templateresolver.StringTemplateResolver;
-
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-public class BruteForceTest {
-
-    private static final String TEMPLATE_NAME = "letter";
-
-    private static final Logger LOG = LoggerFactory.getLogger(BruteForceTest.class);
-
-    @Test
-    public void testClassLoaderTemplateResolverTxt() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.TEXT);
-        resolver.setCharacterEncoding("UTF-8");
-        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
-        resolver.setSuffix(".txt");
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testClassLoaderTemplateResolverHtml() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.HTML);
-        resolver.setCharacterEncoding("UTF-8");
-        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
-        resolver.setSuffix(".html");
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testClassLoaderTemplateResolverXml() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.XML);
-        resolver.setCharacterEncoding("UTF-8");
-        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
-        resolver.setSuffix(".xml");
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testClassLoaderTemplateResolverHtmlAsXml() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.HTML);
-        resolver.setCharacterEncoding("UTF-8");
-        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
-        resolver.setSuffix(".xml");
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testDefaultTemplateResolverTxt() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        DefaultTemplateResolver resolver = new DefaultTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.TEXT);
-        resolver.setTemplate(textTemplate());
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testDefaultTemplateResolverHtml() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        DefaultTemplateResolver resolver = new DefaultTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.HTML);
-        resolver.setTemplate(textTemplate());
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testFileTemplateResolverTxt() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        FileTemplateResolver resolver = new FileTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.TEXT);
-        resolver.setCharacterEncoding("UTF-8");
-        resolver.setPrefix("src/test/resources/org/apache/camel/component/thymeleaf/");
-        resolver.setSuffix(".txt");
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testFileTemplateResolverHtml() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        FileTemplateResolver resolver = new FileTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.HTML);
-        resolver.setCharacterEncoding("UTF-8");
-        resolver.setPrefix("src/test/resources/org/apache/camel/component/thymeleaf/");
-        resolver.setSuffix(".html");
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testFileTemplateResolverTxtAsHtml() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        FileTemplateResolver resolver = new FileTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.HTML);
-        resolver.setCharacterEncoding("UTF-8");
-        resolver.setPrefix("src/test/resources/org/apache/camel/component/thymeleaf/");
-        resolver.setSuffix(".txt");
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testFileTemplateResolverHtmlAsTxt() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        FileTemplateResolver resolver = new FileTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.TEXT);
-        resolver.setCharacterEncoding("UTF-8");
-        resolver.setPrefix("src/test/resources/org/apache/camel/component/thymeleaf/");
-        resolver.setSuffix(".html");
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testFileTemplateResolverNoMode() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        FileTemplateResolver resolver = new FileTemplateResolver();
-        resolver.setCharacterEncoding("UTF-8");
-        resolver.setPrefix("src/test/resources/org/apache/camel/component/thymeleaf/");
-        resolver.setSuffix(".html");
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testStringTemplateResolverTxt() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        StringTemplateResolver resolver = new StringTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.TEXT);
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(textTemplate(), context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testStringTemplateResolverHtml() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-        StringTemplateResolver resolver = new StringTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.HTML);
-        templateEngine.setTemplateResolver(resolver);
-
-        String result = templateEngine.process(textTemplate(), context());
-        LOG.info("\n" + result.trim());
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    protected Context context() {
-
-        Context context = new Context();
-        context.setVariable("headers", headers());
-        context.setVariable("body", body());
-
-        return context;
-    }
-
-    protected Map<String, Object> headers() {
-
-        Map<String, Object> headers = new HashMap<>();
-        headers.put("lastName", "Doe");
-        headers.put("firstName", "Jane");
-        headers.put("item", "Widgets for Dummies");
-
-        return headers;
-    }
-
-    protected Object body() {
-
-        return "Spazz Testing Service";
-    }
-
-    protected String textTemplate() {
-
-        return """
-                <!--/*-->
-                    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.
-                <!--*/-->
-                <!--/* This code will be removed at thymeleaf parsing time! */-->
-                Dear [(${headers.lastName})], [(${headers.firstName})]
-
-                Thanks for the order of [(${headers.item})].
-
-                Regards Camel Riders Bookstore
-                [(${body})]""";
-    }
-
-}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceWebAppResolverTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceWebAppResolverTest.java
deleted file mode 100644
index 2c3263e6a2f..00000000000
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceWebAppResolverTest.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.thymeleaf;
-
-import java.io.File;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Map;
-
-import jakarta.servlet.ServletContext;
-
-import org.apache.commons.io.FileUtils;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.thymeleaf.TemplateEngine;
-import org.thymeleaf.context.Context;
-import org.thymeleaf.templatemode.TemplateMode;
-import org.thymeleaf.templateresolver.WebApplicationTemplateResolver;
-import org.thymeleaf.web.servlet.JakartaServletWebApplication;
-
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.mock;
-
-public class BruteForceWebAppResolverTest {
-
-    private static final String TEMPLATE_NAME = "letter";
-
-    private static final Logger LOG = LoggerFactory.getLogger(BruteForceWebAppResolverTest.class);
-
-    private JakartaServletWebApplication servletWebApplication;
-
-    @BeforeEach
-    public void setUp() throws Exception {
-
-        ServletContext servletContext = mock(ServletContext.class);
-
-        servletWebApplication = JakartaServletWebApplication.buildApplication(servletContext);
-
-        File initialFile = new File("src/test/resources/WEB-INF/templates/letter.html");
-        InputStream targetStream = FileUtils.openInputStream(initialFile);
-        Mockito.when(servletContext.getResourceAsStream(anyString())).thenReturn(targetStream);
-    }
-
-    @Test
-    public void testWebApplicationTemplateResolverHtml() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-
-        WebApplicationTemplateResolver resolver = new WebApplicationTemplateResolver(servletWebApplication);
-        resolver.setTemplateMode(TemplateMode.HTML);
-        resolver.setCharacterEncoding("UTF-8");
-        resolver.setPrefix("/WEB-INF/templates/");
-        resolver.setSuffix(".html");
-
-        templateEngine.addTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.debug("\n" + result);
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    @Test
-    public void testWebApplicationTemplateResolverTxt() {
-
-        TemplateEngine templateEngine = new TemplateEngine();
-
-        WebApplicationTemplateResolver resolver = new WebApplicationTemplateResolver(servletWebApplication);
-        resolver.setTemplateMode(TemplateMode.TEXT);
-        resolver.setCharacterEncoding("UTF-8");
-        resolver.setPrefix("/WEB-INF/templates/");
-        resolver.setSuffix(".html");
-
-        templateEngine.addTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.debug("\n" + result);
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    protected Context context() {
-
-        Context context = new Context();
-        context.setVariable("headers", headers());
-        context.setVariable("body", body());
-
-        return context;
-    }
-
-    protected Object body() {
-
-        return "Spazz Testing Service";
-    }
-
-    protected Map<String, Object> headers() {
-
-        Map<String, Object> headers = new HashMap<>();
-        headers.put("lastName", "Doe");
-        headers.put("firstName", "Jane");
-        headers.put("item", "Widgets for Dummies");
-
-        return headers;
-    }
-
-}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceWiremockTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceWiremockTest.java
deleted file mode 100644
index 8823c1c7bdc..00000000000
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceWiremockTest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.thymeleaf;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
-import com.github.tomakehurst.wiremock.junit5.WireMockTest;
-import org.junit.jupiter.api.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.thymeleaf.TemplateEngine;
-import org.thymeleaf.context.Context;
-import org.thymeleaf.templatemode.TemplateMode;
-import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
-import org.thymeleaf.templateresolver.UrlTemplateResolver;
-
-import static com.github.tomakehurst.wiremock.client.WireMock.get;
-import static com.github.tomakehurst.wiremock.client.WireMock.ok;
-import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-@WireMockTest(httpPort = 9843)
-public class BruteForceWiremockTest {
-
-    private static final String TEMPLATE_NAME = "letterWithUrl";
-
-    private static final Logger LOG = LoggerFactory.getLogger(BruteForceWiremockTest.class);
-
-    @Test
-    public void testUrlTemplateResolver(WireMockRuntimeInfo wmRuntimeInfo) {
-
-        stubFor(get("/dontcare.html").willReturn(ok(fragment())));
-
-        TemplateEngine templateEngine = new TemplateEngine();
-
-        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
-        resolver.setTemplateMode(TemplateMode.HTML);
-        resolver.setCharacterEncoding("UTF-8");
-        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
-        resolver.setSuffix(".html");
-        resolver.setOrder(2);
-
-        UrlTemplateResolver urlTemplateResolver = new UrlTemplateResolver();
-        urlTemplateResolver.setCharacterEncoding("UTF-8");
-        urlTemplateResolver.setOrder(1);
-
-        templateEngine.addTemplateResolver(urlTemplateResolver);
-        templateEngine.addTemplateResolver(resolver);
-
-        String result = templateEngine.process(TEMPLATE_NAME, context());
-        LOG.info("\n" + result);
-
-        assertNotNull(result);
-        assertTrue((result.length() > 0));
-    }
-
-    protected Context context() {
-
-        Context context = new Context();
-        context.setVariable("headers", headers());
-        context.setVariable("body", body());
-
-        return context;
-    }
-
-    protected Object body() {
-
-        return "Spazz Testing Service";
-    }
-
-    protected Map<String, Object> headers() {
-
-        Map<String, Object> headers = new HashMap<>();
-        headers.put("lastName", "Doe");
-        headers.put("firstName", "Jane");
-        headers.put("item", "Widgets for Dummies");
-
-        return headers;
-    }
-
-    protected String fragment() {
-
-        return """
-                <span th:fragment="test" th:remove="tag">
-                You will be notified when your order ships.
-                </span>
-                """;
-    }
-
-}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafAbstractBaseTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafAbstractBaseTest.java
new file mode 100644
index 00000000000..525a949a8a7
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafAbstractBaseTest.java
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit5.CamelTestSupport;
+
+import static java.util.Map.entry;
+
+public abstract class ThymeleafAbstractBaseTest extends CamelTestSupport {
+
+    protected static final String HTML = "HTML";
+
+    protected static final String HTML_SUFFIX = ".html";
+
+    protected static final long CACHE_TIME_TO_LIVE = 500L;
+
+    protected static final String UTF_8_ENCODING = "UTF-8";
+
+    protected static final int ORDER = 1;
+
+    protected static final String PREFIX_SRC_TEST_RESOURCES = "src/test/resources/";
+
+    protected static final String PREFIX_WEB_INF_TEMPLATES = "WEB-INF/templates/";
+
+    protected static final String ORDER_NUMBER = "orderNumber";
+
+    protected static final String JANE = "Jane";
+
+    protected static final String LAST_NAME = "lastName";
+
+    protected static final String FIRST_NAME = "firstName";
+
+    protected static final String ITEM = "item";
+
+    protected static final String SPAZZ_TESTING_SERVICE = "Spazz Testing Service";
+
+    protected static final String THANK_YOU_FOR_YOUR_ORDER = "Thank you for your order number 7 of Widgets for Dummies.";
+
+    protected static final String YOU_WILL_NOTIFIED = "You will be notified when your order ships.";
+
+    protected static final String DIRECT_START = "direct:start";
+
+    protected static final String DIRECT_START_NO_CACHE = "direct:start_a";
+
+    protected static final String DIRECT_START_WITH_CACHE = "direct:start_b";
+
+    protected static final String DIRECT_START_CACHE_TTL = "direct:start_c";
+
+    protected static final String MOCK_RESULT = "mock:result";
+
+    protected BasicHeaderProcessor basicHeaderProcessor = new BasicHeaderProcessor();
+
+    protected ResourceUriHeaderProcessor resourceUriHeaderProcessor = new ResourceUriHeaderProcessor();
+
+    protected TemplateHeaderProcessor templateHeaderProcessor = new TemplateHeaderProcessor();
+
+    protected UrlTemplateHeaderProcessor urlTemplateHeaderProcessor = new UrlTemplateHeaderProcessor();
+
+    protected VariableMapHeaderProcessor variableMapHeaderProcessor = new VariableMapHeaderProcessor();
+
+    protected static String resourceUri() {
+
+        return "org/apache/camel/component/thymeleaf/letter.html";
+    }
+
+    protected static String stringTemplate() {
+
+        return """
+                <!--/*-->
+                    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.
+                <!--*/-->
+                <!--/* This code will be removed at thymeleaf parsing time! */-->
+                Dear [(${headers.lastName})], [(${headers.firstName})]
+
+                Thank you for your order number [(${exchange.properties.orderNumber})] of [(${headers.item})].
+
+                Regards Camel Riders Bookstore
+                [(${body})]""";
+    }
+
+    protected static String urlTemplate() {
+
+        return "http://localhost:9843/dontcare.html";
+    }
+
+    protected static String variableMapTemplate() {
+
+        return """
+                <!--/*-->
+                    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.
+                <!--*/-->
+                <!--/* This code will be removed at thymeleaf parsing time! */-->
+                Dear [(${lastName})], [(${firstName})]
+
+                Thank you for your order number [(${orderNumber})] of [(${item})].
+
+                Regards Camel Riders Bookstore
+                [(${body})]""";
+    }
+
+    protected String expected() {
+
+        return "\n\n" +
+               "Dear Doe, Jane\n" +
+               "\n" +
+               "Thank you for your order number 7 of Widgets for Dummies.\n" +
+               "\n" +
+               "Regards Camel Riders Bookstore\n" +
+               "Spazz Testing Service";
+    }
+
+    @Override
+    protected abstract RouteBuilder createRouteBuilder();
+
+    protected static class BasicHeaderProcessor implements Processor {
+
+        @Override
+        public void process(Exchange exchange) {
+
+            exchange.getIn().setHeader(LAST_NAME, "Doe");
+            exchange.getIn().setHeader(FIRST_NAME, JANE);
+            exchange.getIn().setHeader(ITEM, "Widgets for Dummies");
+
+            exchange.setProperty(ORDER_NUMBER, "7");
+        }
+
+    }
+
+    protected static class ResourceUriHeaderProcessor implements Processor {
+
+        @Override
+        public void process(Exchange exchange) {
+
+            exchange.getIn().setHeader(ThymeleafConstants.THYMELEAF_RESOURCE_URI, resourceUri());
+            exchange.getIn().setHeader(LAST_NAME, "Doe");
+            exchange.getIn().setHeader(FIRST_NAME, JANE);
+            exchange.getIn().setHeader(ITEM, "Widgets for Dummies");
+
+            exchange.setProperty(ORDER_NUMBER, "7");
+        }
+
+    }
+
+    protected static class TemplateHeaderProcessor implements Processor {
+
+        @Override
+        public void process(Exchange exchange) {
+
+            exchange.getIn().setHeader(ThymeleafConstants.THYMELEAF_TEMPLATE, stringTemplate());
+            exchange.getIn().setHeader(LAST_NAME, "Doe");
+            exchange.getIn().setHeader(FIRST_NAME, JANE);
+            exchange.getIn().setHeader(ITEM, "Widgets for Dummies");
+
+            exchange.setProperty(ORDER_NUMBER, "7");
+        }
+
+    }
+
+    protected static class UrlTemplateHeaderProcessor implements Processor {
+
+        @Override
+        public void process(Exchange exchange) {
+
+            exchange.getIn().setHeader(ThymeleafConstants.THYMELEAF_TEMPLATE, urlTemplate());
+            exchange.getIn().setHeader(LAST_NAME, "Doe");
+            exchange.getIn().setHeader(FIRST_NAME, JANE);
+            exchange.getIn().setHeader(ITEM, "Widgets for Dummies");
+
+            exchange.setProperty(ORDER_NUMBER, "7");
+        }
+
+    }
+
+    protected static class VariableMapHeaderProcessor implements Processor {
+
+        @Override
+        public void process(Exchange exchange) {
+
+            exchange.getIn().setHeader(ThymeleafConstants.THYMELEAF_TEMPLATE, variableMapTemplate());
+            Map<String, Object> variables = Map.ofEntries(
+                    entry(LAST_NAME, "Doe"),
+                    entry(FIRST_NAME, JANE),
+                    entry(ITEM, "Widgets for Dummies"),
+                    entry(ORDER_NUMBER, "7"));
+
+            exchange.getIn().setHeader(ThymeleafConstants.THYMELEAF_VARIABLE_MAP, new HashMap<>(variables));
+        }
+
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafAttachmentsTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafAttachmentsTest.java
deleted file mode 100644
index 7e904fe1f66..00000000000
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafAttachmentsTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.thymeleaf;
-
-import jakarta.activation.DataHandler;
-import jakarta.activation.FileDataSource;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Processor;
-import org.apache.camel.attachment.AttachmentMessage;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.test.junit5.CamelTestSupport;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-/**
- * Thymeleaf unit test
- */
-public class ThymeleafAttachmentsTest extends CamelTestSupport {
-
-    @Test
-    public void testThymeleafAttachments() {
-
-        Exchange exchange = template.request("direct:a", new Processor() {
-
-            @Override
-            public void process(Exchange exchange) {
-
-                exchange.setProperty("item", "7");
-
-                AttachmentMessage am = exchange.getIn(AttachmentMessage.class);
-                am.setBody("Monday");
-                am.setHeader("name", "Christian");
-                am.addAttachment("123", new DataHandler(new FileDataSource("pom.xml")));
-            }
-        });
-
-        assertEquals("Dear Christian. You ordered item 7 on Monday.", exchange.getMessage().getBody());
-        assertEquals("Christian", exchange.getMessage().getHeader("name"));
-
-        AttachmentMessage am = exchange.getMessage(AttachmentMessage.class);
-        assertNotNull(am);
-        assertEquals("123", am.getAttachmentNames().iterator().next());
-    }
-
-    @Override
-    protected RouteBuilder createRouteBuilder() {
-
-        return new RouteBuilder() {
-
-            public void configure() {
-                // START SNIPPET: example
-                from("direct:a").to(
-                        "thymeleaf:org/apache/camel/component/thymeleaf/example.txt?allowTemplateFromHeader=true&allowContextMapAll=true");
-                // END SNIPPET: example
-            }
-        };
-    }
-
-}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafBodyAsDomainObjectTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafBodyAsDomainObjectTest.java
index 780212e8e05..8dfac7e68b3 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafBodyAsDomainObjectTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafBodyAsDomainObjectTest.java
@@ -18,26 +18,26 @@ package org.apache.camel.component.thymeleaf;
 
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.test.junit5.CamelTestSupport;
 import org.junit.jupiter.api.Test;
 
-/**
- * Unit test with the body as a Domain object.
- */
-public class ThymeleafBodyAsDomainObjectTest extends CamelTestSupport {
+public class ThymeleafBodyAsDomainObjectTest extends ThymeleafAbstractBaseTest {
 
     @Test
-    public void testWithObject() throws Exception {
+    public void testThymeleaf() throws InterruptedException {
 
-        MockEndpoint mock = getMockEndpoint("mock:result");
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
         mock.expectedMessageCount(1);
-        mock.message(0).body().contains("Hi Claus how are you? Its a nice day.");
+        mock.message(0).body().contains(THANK_YOU_FOR_YOUR_ORDER);
+        mock.message(0).body().endsWith(SPAZZ_TESTING_SERVICE);
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_TEMPLATE).isNull();
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_VARIABLE_MAP).isNull();
+        mock.message(0).header(FIRST_NAME).isNull();
 
-        MyPerson person = new MyPerson();
-        person.setFamilyName("Ibsen");
-        person.setGivenName("Claus");
+        template.request(DIRECT_START, exchange -> {
 
-        template.requestBody("direct:in", person);
+            exchange.getIn().setBody(letter());
+            exchange.setProperty(ORDER_NUMBER, "7");
+        });
 
         mock.assertIsSatisfied();
     }
@@ -49,48 +49,83 @@ public class ThymeleafBodyAsDomainObjectTest extends CamelTestSupport {
 
             public void configure() {
 
-                from("direct:in")
-                        .to("thymeleaf:org/apache/camel/component/thymeleaf/BodyAsDomainObject.txt")
-                        .to("mock:result");
+                from(DIRECT_START)
+                        .to("thymeleaf:org/apache/camel/component/thymeleaf/letter-domain.html?allowContextMapAll=true")
+                        .to(MOCK_RESULT);
             }
         };
     }
 
-    public static class MyPerson {
+    private Letter letter() {
+
+        Letter letter = new Letter();
+        letter.setFirstName(JANE);
+        letter.setLastName("Doe");
+        letter.setItem("Widgets for Dummies");
+        letter.setClosing(SPAZZ_TESTING_SERVICE);
+
+        return letter;
+    }
+
+    static class Letter {
 
-        private String givenName;
+        private String firstName;
 
-        private String familyName;
+        private String lastName;
+
+        private String item;
+
+        private String closing;
+
+        public String getFirstName() {
+
+            return firstName;
+        }
+
+        public void setFirstName(String firstName) {
+
+            this.firstName = firstName;
+        }
+
+        public String getLastName() {
+
+            return lastName;
+        }
+
+        public void setLastName(String lastName) {
+
+            this.lastName = lastName;
+        }
 
-        public String getGivenName() {
+        public String getItem() {
 
-            return givenName;
+            return item;
         }
 
-        public void setGivenName(String givenName) {
+        public void setItem(String item) {
 
-            this.givenName = givenName;
+            this.item = item;
         }
 
-        public String getFamilyName() {
+        public String getClosing() {
 
-            return familyName;
+            return closing;
         }
 
-        public void setFamilyName(String familyName) {
+        public void setClosing(String closing) {
 
-            this.familyName = familyName;
+            this.closing = closing;
         }
 
         @Override
         public String toString() {
 
-            return "MyPerson{"
-                   + "givenName='"
-                   + givenName + '\''
-                   + ", familyName='"
-                   + familyName + '\''
-                   + '}';
+            return "Letter{" +
+                   "firstName='" + firstName + '\'' +
+                   ", lastName='" + lastName + '\'' +
+                   ", item='" + item + '\'' +
+                   ", closing='" + closing + '\'' +
+                   '}';
         }
 
     }
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafClassLoaderResolverAllParamsTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafClassLoaderResolverAllParamsTest.java
new file mode 100644
index 00000000000..f670b746366
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafClassLoaderResolverAllParamsTest.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
+import org.thymeleaf.templateresolver.ITemplateResolver;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class ThymeleafClassLoaderResolverAllParamsTest extends ThymeleafAbstractBaseTest {
+
+    @Test
+    public void testThymeleaf() throws InterruptedException {
+
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedMessageCount(1);
+        mock.message(0).body().contains(THANK_YOU_FOR_YOUR_ORDER);
+        mock.message(0).body().endsWith(SPAZZ_TESTING_SERVICE);
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_TEMPLATE).isNull();
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_VARIABLE_MAP).isNull();
+        mock.message(0).header(FIRST_NAME).isEqualTo(JANE);
+
+        template.request(DIRECT_START, basicHeaderProcessor);
+
+        mock.assertIsSatisfied();
+
+        ThymeleafEndpoint thymeleafEndpoint = context.getEndpoint(
+                "thymeleaf:letter?allowContextMapAll=true&cacheable=false&cacheTimeToLive=500&checkExistence=true&encoding=UTF-8&order=1&prefix=WEB-INF/templates/&resolver=CLASS_LOADER&suffix=.html",
+                ThymeleafEndpoint.class);
+
+        assertAll("properties",
+                () -> assertNotNull(thymeleafEndpoint),
+                () -> assertTrue(thymeleafEndpoint.isAllowContextMapAll()),
+                () -> assertFalse(thymeleafEndpoint.getCacheable()),
+                () -> assertEquals(CACHE_TIME_TO_LIVE, thymeleafEndpoint.getCacheTimeToLive()),
+                () -> assertTrue(thymeleafEndpoint.getCheckExistence()),
+                () -> assertEquals(UTF_8_ENCODING, thymeleafEndpoint.getEncoding()),
+                () -> assertEquals(ExchangePattern.InOut, thymeleafEndpoint.getExchangePattern()),
+                () -> assertEquals(ORDER, thymeleafEndpoint.getOrder()),
+                () -> assertEquals(PREFIX_WEB_INF_TEMPLATES, thymeleafEndpoint.getPrefix()),
+                () -> assertEquals(ThymeleafResolverType.CLASS_LOADER, thymeleafEndpoint.getResolver()),
+                () -> assertEquals(HTML_SUFFIX, thymeleafEndpoint.getSuffix()),
+                () -> assertNotNull(thymeleafEndpoint.getTemplateEngine()),
+                () -> assertNull(thymeleafEndpoint.getTemplateMode()));
+
+        assertEquals(1, thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().size());
+        ITemplateResolver resolver = thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().stream().findFirst().get();
+        assertTrue(resolver instanceof ClassLoaderTemplateResolver);
+
+        ClassLoaderTemplateResolver templateResolver = (ClassLoaderTemplateResolver) resolver;
+        assertAll("templateResolver",
+                () -> assertFalse(templateResolver.isCacheable()),
+                () -> assertEquals(CACHE_TIME_TO_LIVE, templateResolver.getCacheTTLMs()),
+                () -> assertEquals(UTF_8_ENCODING, templateResolver.getCharacterEncoding()),
+                () -> assertTrue(templateResolver.getCheckExistence()),
+                () -> assertEquals(ORDER, templateResolver.getOrder()),
+                () -> assertEquals(PREFIX_WEB_INF_TEMPLATES, templateResolver.getPrefix()),
+                () -> assertEquals(HTML_SUFFIX, templateResolver.getSuffix()),
+                () -> assertEquals(TemplateMode.HTML, templateResolver.getTemplateMode()));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+
+                from(DIRECT_START)
+                        .setBody(simple(SPAZZ_TESTING_SERVICE))
+                        .to("thymeleaf:letter?allowContextMapAll=true&cacheable=false&cacheTimeToLive=500&checkExistence=true&encoding=UTF-8&order=1&prefix=WEB-INF/templates/&resolver=CLASS_LOADER&suffix=.html")
+                        .to(MOCK_RESULT);
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafClassLoaderResolverTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafClassLoaderResolverTest.java
new file mode 100644
index 00000000000..c9de8c5f548
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafClassLoaderResolverTest.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
+import org.thymeleaf.templateresolver.ITemplateResolver;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class ThymeleafClassLoaderResolverTest extends ThymeleafAbstractBaseTest {
+
+    @Test
+    public void testThymeleaf() throws InterruptedException {
+
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedMessageCount(1);
+        mock.message(0).body().contains(THANK_YOU_FOR_YOUR_ORDER);
+        mock.message(0).body().endsWith(SPAZZ_TESTING_SERVICE);
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_TEMPLATE).isNull();
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_VARIABLE_MAP).isNull();
+        mock.message(0).header(FIRST_NAME).isEqualTo(JANE);
+
+        template.request(DIRECT_START, basicHeaderProcessor);
+
+        mock.assertIsSatisfied();
+
+        ThymeleafEndpoint thymeleafEndpoint = context.getEndpoint(
+                "thymeleaf:org/apache/camel/component/thymeleaf/letter.html?allowContextMapAll=true&resolver=CLASS_LOADER",
+                ThymeleafEndpoint.class);
+
+        assertAll("properties",
+                () -> assertNotNull(thymeleafEndpoint),
+                () -> assertTrue(thymeleafEndpoint.isAllowContextMapAll()),
+                () -> assertNull(thymeleafEndpoint.getCacheable()),
+                () -> assertNull(thymeleafEndpoint.getCacheTimeToLive()),
+                () -> assertNull(thymeleafEndpoint.getCheckExistence()),
+                () -> assertNull(thymeleafEndpoint.getEncoding()),
+                () -> assertEquals(ExchangePattern.InOut, thymeleafEndpoint.getExchangePattern()),
+                () -> assertNull(thymeleafEndpoint.getOrder()),
+                () -> assertNull(thymeleafEndpoint.getPrefix()),
+                () -> assertEquals(ThymeleafResolverType.CLASS_LOADER, thymeleafEndpoint.getResolver()),
+                () -> assertNull(thymeleafEndpoint.getSuffix()),
+                () -> assertNotNull(thymeleafEndpoint.getTemplateEngine()),
+                () -> assertNull(thymeleafEndpoint.getTemplateMode()));
+
+        assertEquals(1, thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().size());
+        ITemplateResolver resolver = thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().stream().findFirst().get();
+        assertTrue(resolver instanceof ClassLoaderTemplateResolver);
+
+        ClassLoaderTemplateResolver templateResolver = (ClassLoaderTemplateResolver) resolver;
+        assertAll("templateResolver",
+                () -> assertTrue(templateResolver.isCacheable()),
+                () -> assertNull(templateResolver.getCacheTTLMs()),
+                () -> assertNull(templateResolver.getCharacterEncoding()),
+                () -> assertFalse(templateResolver.getCheckExistence()),
+                () -> assertNull(templateResolver.getOrder()),
+                () -> assertNull(templateResolver.getPrefix()),
+                () -> assertNull(templateResolver.getSuffix()),
+                () -> assertEquals(TemplateMode.HTML, templateResolver.getTemplateMode()));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+
+                from(DIRECT_START)
+                        .setBody(simple(SPAZZ_TESTING_SERVICE))
+                        .to("thymeleaf:org/apache/camel/component/thymeleaf/letter.html?allowContextMapAll=true&resolver=CLASS_LOADER")
+                        .to(MOCK_RESULT);
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafComponentTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafComponentTest.java
new file mode 100644
index 00000000000..a1b403673f7
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafComponentTest.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.component.thymeleaf;
+
+import java.util.UUID;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.support.PropertyBindingListener;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.ITemplateResolver;
+import org.thymeleaf.templateresolver.StringTemplateResolver;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.spy;
+
+public class ThymeleafComponentTest extends ThymeleafAbstractBaseTest {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ThymeleafComponentTest.class);
+
+    private String templateMode;
+
+    @Test
+    public void testThymeleaf() throws InterruptedException {
+
+        ThymeleafComponent component = context.getComponent("thymeleaf", ThymeleafComponent.class);
+        assertNotNull(component);
+
+        ThymeleafEndpoint thymeleafEndpoint = context.getEndpoint(
+                "thymeleaf:dontcare?templateMode=CSS&allowContextMapAll=true&resolver=STRING",
+                ThymeleafEndpoint.class);
+
+        ThymeleafEndpoint spy = spy(thymeleafEndpoint);
+        LOG.info("foo: {}",
+                thymeleafEndpoint.getComponent().getEndpointPropertyConfigurer().getClass());
+
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedMessageCount(1);
+
+        template.request(DIRECT_START, templateHeaderProcessor);
+
+        mock.assertIsSatisfied();
+
+        assertEquals(TemplateMode.CSS.name(), thymeleafEndpoint.getTemplateMode());
+
+        assertEquals(1, thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().size());
+        ITemplateResolver resolver = thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().stream().findFirst().get();
+        assertTrue(resolver instanceof StringTemplateResolver);
+
+        StringTemplateResolver templateResolver = (StringTemplateResolver) resolver;
+        assertEquals(TemplateMode.CSS, templateResolver.getTemplateMode());
+        assertEquals(TemplateMode.CSS.name(), templateMode);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+
+                from(DIRECT_START)
+                        .setBody(simple(SPAZZ_TESTING_SERVICE))
+                        .to("thymeleaf:dontcare?templateMode=CSS&allowContextMapAll=true&resolver=STRING")
+                        .to(MOCK_RESULT);
+
+                /*
+                 * Listens for the templateMode property binding to allow verification of the <code>createEndpoint()</code>
+                 * method in <code>ThymeleafComponent</code>.
+                 */
+                getCamelContext().getRegistry().bind(UUID.randomUUID().toString(),
+                        (PropertyBindingListener) (target, key, value) -> {
+                            if ("templateMode".equals(key)) {
+                                templateMode = (String) value;
+                            }
+                        });
+            }
+        };
+    }
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafConcurrentTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafConcurrentTest.java
index deeb950f10b..d38f6796379 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafConcurrentTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafConcurrentTest.java
@@ -16,18 +16,16 @@
  */
 package org.apache.camel.component.thymeleaf;
 
-import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.test.junit5.CamelTestSupport;
 import org.junit.jupiter.api.Test;
 
 import static org.apache.camel.test.junit5.TestSupport.body;
 
-public class ThymeleafConcurrentTest extends CamelTestSupport {
+public class ThymeleafConcurrentTest extends ThymeleafAbstractBaseTest {
 
     @Test
     public void testNoConcurrentProducers() throws Exception {
@@ -43,20 +41,20 @@ public class ThymeleafConcurrentTest extends CamelTestSupport {
 
     private void doSendMessages(int files, int poolSize) throws Exception {
 
-        getMockEndpoint("mock:result").expectedMessageCount(files);
-        getMockEndpoint("mock:result").assertNoDuplicates(body());
-        getMockEndpoint("mock:result").message(0).body().contains("Bye");
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+
+        mock.expectedMessageCount(files);
+        mock.assertNoDuplicates(body());
+        mock.message(0).body().contains("Bye");
 
         ExecutorService executor = Executors.newFixedThreadPool(poolSize);
         for (int i = 0; i < files; i++) {
             final int index = i;
-            executor.submit(new Callable<Object>() {
+            executor.submit(() -> {
 
-                public Object call() {
+                template.sendBody(DIRECT_START, "Hello " + index);
 
-                    template.sendBody("direct:start", "Hello " + index);
-                    return null;
-                }
+                return null;
             });
         }
 
@@ -71,7 +69,9 @@ public class ThymeleafConcurrentTest extends CamelTestSupport {
 
             public void configure() {
 
-                from("direct:start").to("thymeleaf:org/apache/camel/component/thymeleaf/Concurrent.txt").to("mock:result");
+                from(DIRECT_START)
+                        .to("thymeleaf:org/apache/camel/component/thymeleaf/concurrent.txt")
+                        .to(MOCK_RESULT);
             }
         };
     }
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafContentCacheTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafContentCacheTest.java
index 7d0bf7c3465..950836a1fa6 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafContentCacheTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafContentCacheTest.java
@@ -16,7 +16,8 @@
  */
 package org.apache.camel.component.thymeleaf;
 
-import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Set;
 
 import javax.management.MBeanServer;
@@ -25,14 +26,14 @@ import javax.management.ObjectName;
 import org.apache.camel.Exchange;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.test.junit5.CamelTestSupport;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
 
-/**
- * Unit test the cache when reloading .ftl files in the classpath
- */
-public class ThymeleafContentCacheTest extends CamelTestSupport {
+import static java.util.Map.entry;
+
+@TestInstance(TestInstance.Lifecycle.PER_METHOD)
+public class ThymeleafContentCacheTest extends ThymeleafAbstractBaseTest {
 
     @Override
     public boolean useJmx() {
@@ -46,127 +47,150 @@ public class ThymeleafContentCacheTest extends CamelTestSupport {
 
         super.setUp();
 
-        // create a vm file in the classpath as this is the tricky reloading stuff
-        template.sendBodyAndHeader("file://target/test-classes/org/apache/camel/component/thymeleaf?fileExist=Override",
-                "Hello ${headers.name}", Exchange.FILE_NAME, "hello.ftl");
+        // create a template file in the classpath
+        template.sendBodyAndHeader(
+                "file://target/test-classes/org/apache/camel/component/thymeleaf?fileExist=Override",
+                stringTemplate(), Exchange.FILE_NAME, "letter-cached.html");
     }
 
     @Test
     public void testNotCached() throws Exception {
 
-        MockEndpoint mock = getMockEndpoint("mock:result");
-        mock.expectedBodiesReceived("Hello London");
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedBodiesReceived(expected());
 
-        template.sendBodyAndHeader("direct:a", "Body", "name", "London");
+        Map<String, Object> headerMap = new HashMap<>(
+                Map.ofEntries(entry(LAST_NAME, "Doe"), entry(FIRST_NAME, JANE), entry(ITEM, "Widgets for Dummies")));
+
+        template.sendBodyAndHeaders(DIRECT_START_NO_CACHE, SPAZZ_TESTING_SERVICE, headerMap);
         mock.assertIsSatisfied();
 
         // now change content in the file in the classpath and try again
         template.sendBodyAndHeader("file://target/test-classes/org/apache/camel/component/thymeleaf?fileExist=Override",
-                "Bye ${headers.name}", Exchange.FILE_NAME, "hello.ftl");
+                "not-cached\n" + stringTemplate(), Exchange.FILE_NAME, "letter-cached.html");
 
         mock.reset();
-        mock.expectedBodiesReceived("Bye Paris");
+        mock.expectedBodiesReceived(expectedNoCache());
 
-        template.sendBodyAndHeader("direct:a", "Body", "name", "Paris");
+        template.sendBodyAndHeaders(DIRECT_START_NO_CACHE, SPAZZ_TESTING_SERVICE, headerMap);
         mock.assertIsSatisfied();
     }
 
     @Test
     public void testCached() throws Exception {
 
-        MockEndpoint mock = getMockEndpoint("mock:result");
-        mock.expectedBodiesReceived("Hello London");
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedBodiesReceived(expected());
+
+        Map<String, Object> headerMap = new HashMap<>(
+                Map.ofEntries(entry(LAST_NAME, "Doe"), entry(FIRST_NAME, JANE), entry(ITEM, "Widgets for Dummies")));
 
-        template.sendBodyAndHeader("direct:b", "Body", "name", "London");
+        template.sendBodyAndHeaders(DIRECT_START_WITH_CACHE, SPAZZ_TESTING_SERVICE, headerMap);
         mock.assertIsSatisfied();
 
         // now change content in the file in the classpath and try again
         template.sendBodyAndHeader("file://target/test-classes/org/apache/camel/component/thymeleaf?fileExist=Override",
-                "Bye ${headers.name}", Exchange.FILE_NAME, "hello.ftl");
+                "not-cached\n" + stringTemplate(), Exchange.FILE_NAME, "letter-cached.html");
 
         mock.reset();
-        // we must expected the original filecontent as the cache is enabled, so its Hello and not Bye
-        mock.expectedBodiesReceived("Hello Paris");
+        // we must expect the original file content since caching is enabled
+        mock.expectedBodiesReceived(expected());
 
-        template.sendBodyAndHeader("direct:b", "Body", "name", "Paris");
+        template.sendBodyAndHeaders(DIRECT_START_WITH_CACHE, SPAZZ_TESTING_SERVICE, headerMap);
         mock.assertIsSatisfied();
     }
 
     @Test
-    public void testTemplateUpdateDelay() throws Exception {
+    public void testCachedWithDelay() throws Exception {
 
-        MockEndpoint mock = getMockEndpoint("mock:result");
-        mock.expectedBodiesReceived("Hello London");
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedBodiesReceived(expected());
 
-        template.sendBodyAndHeader("direct:c", "Body", "name", "London");
+        Map<String, Object> headerMap = new HashMap<>(
+                Map.ofEntries(entry(LAST_NAME, "Doe"), entry(FIRST_NAME, JANE), entry(ITEM, "Widgets for Dummies")));
+
+        template.sendBodyAndHeaders(DIRECT_START_CACHE_TTL, SPAZZ_TESTING_SERVICE, headerMap);
         mock.assertIsSatisfied();
 
         // now change content in the file in the classpath and try again .... with no delay
         template.sendBodyAndHeader("file://target/test-classes/org/apache/camel/component/thymeleaf?fileExist=Override",
-                "Bye ${headers.name}", Exchange.FILE_NAME, "hello.ftl");
+                "not-cached\n" + stringTemplate(), Exchange.FILE_NAME, "letter-cached.html");
 
         mock.reset();
-        // we must expected the original filecontent as the cache is enabled, so its Hello and not Bye
-        mock.expectedBodiesReceived("Hello Paris");
+        // we must expect the original file content since caching is enabled
+        mock.expectedBodiesReceived(expected());
 
-        template.sendBodyAndHeader("direct:c", "Body", "name", "Paris");
+        template.sendBodyAndHeaders(DIRECT_START_CACHE_TTL, SPAZZ_TESTING_SERVICE, headerMap);
         mock.assertIsSatisfied();
 
         // now change content in the file in the classpath and try again .... after delaying longer than the cache update delay
-        Thread.sleep(2000);
+        Thread.sleep(1000);
         template.sendBodyAndHeader("file://target/test-classes/org/apache/camel/component/thymeleaf?fileExist=Override",
-                "Bye ${headers.name}", Exchange.FILE_NAME, "hello.ftl");
+                "not-cached\n" + stringTemplate(), Exchange.FILE_NAME, "letter-cached.html");
 
         mock.reset();
-        // we must expected the new content, because the cache has expired
-        mock.expectedBodiesReceived("Bye Paris");
-        template.sendBodyAndHeader("direct:c", "Body", "name", "Paris");
+        // we must expect the new content, because the cache has expired
+        mock.expectedBodiesReceived(expectedNoCache());
+
+        template.sendBodyAndHeaders(DIRECT_START_CACHE_TTL, SPAZZ_TESTING_SERVICE, headerMap);
         mock.assertIsSatisfied();
     }
 
     @Test
     public void testClearCacheViaJmx() throws Exception {
 
-        MockEndpoint mock = getMockEndpoint("mock:result");
-        mock.expectedBodiesReceived("Hello London");
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedBodiesReceived(expected());
+
+        Map<String, Object> headerMap = new HashMap<>(
+                Map.ofEntries(entry(LAST_NAME, "Doe"), entry(FIRST_NAME, JANE), entry(ITEM, "Widgets for Dummies")));
 
-        template.sendBodyAndHeader("direct:b", "Body", "name", "London");
+        template.sendBodyAndHeaders(DIRECT_START_WITH_CACHE, SPAZZ_TESTING_SERVICE, headerMap);
         mock.assertIsSatisfied();
 
         // now change content in the file in the classpath and try again
         template.sendBodyAndHeader("file://target/test-classes/org/apache/camel/component/thymeleaf?fileExist=Override",
-                "Bye ${headers.name}", Exchange.FILE_NAME, "hello.ftl");
+                "not-cached\n" + stringTemplate(), Exchange.FILE_NAME, "letter-cached.html");
 
         mock.reset();
-        // we must expected the original filecontent as the cache is enabled, so its Hello and not Bye
-        mock.expectedBodiesReceived("Hello Paris");
 
-        template.sendBodyAndHeader("direct:b", "Body", "name", "Paris");
+        // we must expect the original file content since caching is enabled
+        mock.expectedBodiesReceived(expected());
+
+        template.sendBodyAndHeaders(DIRECT_START_WITH_CACHE, SPAZZ_TESTING_SERVICE, headerMap);
         mock.assertIsSatisfied();
 
         // clear the cache via the mbean server
         MBeanServer mbeanServer = context.getManagementStrategy().getManagementAgent().getMBeanServer();
-        Set<ObjectName> objNameSet = mbeanServer
-                .queryNames(new ObjectName("org.apache.camel:type=endpoints,name=\"thymeleaf:*contentCache=true*\",*"), null);
-        ObjectName managedObjName = new ArrayList<>(objNameSet).get(0);
-        mbeanServer.invoke(managedObjName, "clearContentCache", null, null);
+        Set<ObjectName> objNameSet = mbeanServer.queryNames(
+                new ObjectName("org.apache.camel:type=endpoints,name=\"thymeleaf:*cacheable=true*\",*"), null);
+        // each endpoint has its own template resolver, so cycle through all of them
+        for (ObjectName objectName : objNameSet) {
+            mbeanServer.invoke(objectName, "clearContentCache", null, null);
+        }
 
         // change content in the file in the classpath and try again
-        template.sendBodyAndHeader("file://target/test-classes/org/apache/camel/component/thymeleaf?fileExist=Override",
-                "Bye ${headers.name}", Exchange.FILE_NAME, "hello.ftl");
+        template.sendBodyAndHeader(
+                "file://target/test-classes/org/apache/camel/component/thymeleaf?fileExist=Override",
+                "not-cached\n" + stringTemplate(), Exchange.FILE_NAME, "letter-cached.html");
         mock.reset();
-        // we expect the updated file content because the cache was cleared
-        mock.expectedBodiesReceived("Bye Paris");
-        template.sendBodyAndHeader("direct:b", "Body", "name", "Paris");
+
+        // we expect the updated file content because caching was disabled
+        mock.expectedBodiesReceived(expectedNoCache());
+
+        template.sendBodyAndHeaders(DIRECT_START_WITH_CACHE, SPAZZ_TESTING_SERVICE, headerMap);
         mock.assertIsSatisfied();
 
         // change content in the file in the classpath and try again to verify that the caching is still in effect after clearing the cache
-        template.sendBodyAndHeader("file://target/test-classes/org/apache/camel/component/thymeleaf?fileExist=Override",
-                "Hello ${headers.name}", Exchange.FILE_NAME, "hello.ftl");
+        template.sendBodyAndHeader(
+                "file://target/test-classes/org/apache/camel/component/thymeleaf?fileExist=Override",
+                stringTemplate(), Exchange.FILE_NAME, "letter-cached.html");
         mock.reset();
+
         // we expect the cached content from the prior update
-        mock.expectedBodiesReceived("Bye Paris");
-        template.sendBodyAndHeader("direct:b", "Body", "name", "Paris");
+        mock.expectedBodiesReceived(expectedNoCache());
+
+        template.sendBodyAndHeaders(DIRECT_START_WITH_CACHE, SPAZZ_TESTING_SERVICE, headerMap);
         mock.assertIsSatisfied();
     }
 
@@ -177,17 +201,29 @@ public class ThymeleafContentCacheTest extends CamelTestSupport {
 
             public void configure() {
 
-                from("direct:a").to("thymeleaf://org/apache/camel/component/thymeleaf/hello.ftl?contentCache=false")
-                        .to("mock:result");
+                context.setTracing(true);
 
-                from("direct:b").to("thymeleaf://org/apache/camel/component/thymeleaf/hello.ftl?contentCache=true")
-                        .to("mock:result");
+                from(DIRECT_START_NO_CACHE)
+                        .setProperty(ORDER_NUMBER, simple("7"))
+                        .to("thymeleaf://org/apache/camel/component/thymeleaf/letter-cached.html?cacheable=false&allowContextMapAll=true")
+                        .to(MOCK_RESULT);
 
-                from("direct:c").to(
-                        "thymeleaf://org/apache/camel/component/thymeleaf/hello.ftl?contentCache=true&templateUpdateDelay=1")
-                        .to("mock:result");
+                from(DIRECT_START_WITH_CACHE)
+                        .setProperty(ORDER_NUMBER, simple("7"))
+                        .to("thymeleaf://org/apache/camel/component/thymeleaf/letter-cached.html?cacheable=true&allowContextMapAll=true")
+                        .to(MOCK_RESULT);
+
+                from(DIRECT_START_CACHE_TTL)
+                        .setProperty(ORDER_NUMBER, simple("7"))
+                        .to("thymeleaf://org/apache/camel/component/thymeleaf/letter-cached.html?cacheable=true&cacheTimeToLive=100&allowContextMapAll=true")
+                        .to(MOCK_RESULT);
             }
         };
     }
 
+    private String expectedNoCache() {
+
+        return "not-cached\n" + expected();
+    }
+
 }
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafDefaultResolverAllParamsTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafDefaultResolverAllParamsTest.java
new file mode 100644
index 00000000000..8596c2fef59
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafDefaultResolverAllParamsTest.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.DefaultTemplateResolver;
+import org.thymeleaf.templateresolver.ITemplateResolver;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class ThymeleafDefaultResolverAllParamsTest extends ThymeleafAbstractBaseTest {
+
+    @Test
+    public void testThymeleaf() throws InterruptedException {
+
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedMessageCount(1);
+        mock.message(0).body().contains(THANK_YOU_FOR_YOUR_ORDER);
+        mock.message(0).body().endsWith(SPAZZ_TESTING_SERVICE);
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_TEMPLATE).isNull();
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_VARIABLE_MAP).isNull();
+        mock.message(0).header(FIRST_NAME).isEqualTo(JANE);
+
+        template.request(DIRECT_START, templateHeaderProcessor);
+
+        mock.assertIsSatisfied();
+
+        ThymeleafEndpoint thymeleafEndpoint = context.getEndpoint(
+                "thymeleaf:dontcare?allowContextMapAll=true&checkExistence=false&order=1&resolver=DEFAULT",
+                ThymeleafEndpoint.class);
+
+        assertAll("properties",
+                () -> assertNotNull(thymeleafEndpoint),
+                () -> assertTrue(thymeleafEndpoint.isAllowContextMapAll()),
+                () -> assertNull(thymeleafEndpoint.getCacheable()),
+                () -> assertNull(thymeleafEndpoint.getCacheTimeToLive()),
+                () -> assertFalse(thymeleafEndpoint.getCheckExistence()),
+                () -> assertNull(thymeleafEndpoint.getEncoding()),
+                () -> assertEquals(ExchangePattern.InOut, thymeleafEndpoint.getExchangePattern()),
+                () -> assertEquals(ORDER, thymeleafEndpoint.getOrder()),
+                () -> assertNull(thymeleafEndpoint.getPrefix()),
+                () -> assertEquals(ThymeleafResolverType.DEFAULT, thymeleafEndpoint.getResolver()),
+                () -> assertNull(thymeleafEndpoint.getSuffix()),
+                () -> assertNotNull(thymeleafEndpoint.getTemplateEngine()),
+                () -> assertNull(thymeleafEndpoint.getTemplateMode()));
+
+        assertEquals(1, thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().size());
+        ITemplateResolver resolver = thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().stream().findFirst().get();
+        assertTrue(resolver instanceof DefaultTemplateResolver);
+
+        DefaultTemplateResolver templateResolver = (DefaultTemplateResolver) resolver;
+        assertAll("templateResolver",
+                () -> assertFalse(templateResolver.getCheckExistence()),
+                () -> assertEquals(ORDER, templateResolver.getOrder()),
+                () -> assertEquals(TemplateMode.HTML, templateResolver.getTemplateMode()));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+
+                from(DIRECT_START)
+                        .setBody(simple(SPAZZ_TESTING_SERVICE))
+                        .to("thymeleaf:dontcare?allowContextMapAll=true&checkExistence=false&order=1&resolver=DEFAULT")
+                        .to(MOCK_RESULT);
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafDefaultResolverTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafDefaultResolverTest.java
new file mode 100644
index 00000000000..42c442186d9
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafDefaultResolverTest.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.DefaultTemplateResolver;
+import org.thymeleaf.templateresolver.ITemplateResolver;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class ThymeleafDefaultResolverTest extends ThymeleafAbstractBaseTest {
+
+    @Test
+    public void testThymeleaf() throws InterruptedException {
+
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedMessageCount(1);
+        mock.message(0).body().contains(THANK_YOU_FOR_YOUR_ORDER);
+        mock.message(0).body().endsWith(SPAZZ_TESTING_SERVICE);
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_TEMPLATE).isNull();
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_VARIABLE_MAP).isNull();
+        mock.message(0).header(FIRST_NAME).isEqualTo(JANE);
+
+        template.request(DIRECT_START, templateHeaderProcessor);
+
+        mock.assertIsSatisfied();
+
+        ThymeleafEndpoint thymeleafEndpoint = context.getEndpoint(
+                "thymeleaf:dontcare?templateMode=HTML&allowContextMapAll=true&resolver=DEFAULT",
+                ThymeleafEndpoint.class);
+
+        assertAll("properties",
+                () -> assertNotNull(thymeleafEndpoint),
+                () -> assertTrue(thymeleafEndpoint.isAllowContextMapAll()),
+                () -> assertNull(thymeleafEndpoint.getCacheable()),
+                () -> assertNull(thymeleafEndpoint.getCacheTimeToLive()),
+                () -> assertNull(thymeleafEndpoint.getCheckExistence()),
+                () -> assertNull(thymeleafEndpoint.getEncoding()),
+                () -> assertEquals(ExchangePattern.InOut, thymeleafEndpoint.getExchangePattern()),
+                () -> assertNull(thymeleafEndpoint.getOrder()),
+                () -> assertNull(thymeleafEndpoint.getPrefix()),
+                () -> assertEquals(ThymeleafResolverType.DEFAULT, thymeleafEndpoint.getResolver()),
+                () -> assertNull(thymeleafEndpoint.getSuffix()),
+                () -> assertNotNull(thymeleafEndpoint.getTemplateEngine()),
+                () -> assertEquals(HTML, thymeleafEndpoint.getTemplateMode()));
+
+        assertEquals(1, thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().size());
+        ITemplateResolver resolver = thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().stream().findFirst().get();
+        assertTrue(resolver instanceof DefaultTemplateResolver);
+
+        DefaultTemplateResolver templateResolver = (DefaultTemplateResolver) resolver;
+        assertAll("templateResolver",
+                () -> assertFalse(templateResolver.getCheckExistence()),
+                () -> assertNull(templateResolver.getOrder()),
+                () -> assertEquals(TemplateMode.HTML, templateResolver.getTemplateMode()));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+
+                from(DIRECT_START)
+                        .setBody(simple(SPAZZ_TESTING_SERVICE))
+                        .to("thymeleaf:dontcare?templateMode=HTML&allowContextMapAll=true&resolver=DEFAULT")
+                        .to(MOCK_RESULT);
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointTest.java
index bbaf243029d..91b6f5b564d 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointTest.java
@@ -16,12 +16,72 @@
  */
 package org.apache.camel.component.thymeleaf;
 
+import org.apache.camel.ExchangePattern;
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
+import org.thymeleaf.templateresolver.ITemplateResolver;
 
-/**
- * Thymeleaf unit test
- */
-public class ThymeleafEndpointTest extends ThymeleafTest {
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class ThymeleafEndpointTest extends ThymeleafAbstractBaseTest {
+
+    private static final String TEST_ENDPOINT = "testEndpoint";
+
+    @Test
+    public void testThymeleaf() throws InterruptedException {
+
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedMessageCount(1);
+        mock.message(0).body().contains(THANK_YOU_FOR_YOUR_ORDER);
+        mock.message(0).body().endsWith(SPAZZ_TESTING_SERVICE);
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_TEMPLATE).isNull();
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_VARIABLE_MAP).isNull();
+        mock.message(0).header(FIRST_NAME).isEqualTo(JANE);
+
+        template.request(DIRECT_START, basicHeaderProcessor);
+
+        mock.assertIsSatisfied();
+
+        ThymeleafEndpoint thymeleafEndpoint = context.getEndpoint(TEST_ENDPOINT, ThymeleafEndpoint.class);
+
+        assertAll("properties",
+                () -> assertNotNull(thymeleafEndpoint),
+                () -> assertTrue(thymeleafEndpoint.isAllowContextMapAll()),
+                () -> assertNull(thymeleafEndpoint.getCacheable()),
+                () -> assertNull(thymeleafEndpoint.getCacheTimeToLive()),
+                () -> assertNull(thymeleafEndpoint.getCheckExistence()),
+                () -> assertNull(thymeleafEndpoint.getEncoding()),
+                () -> assertEquals(ExchangePattern.InOut, thymeleafEndpoint.getExchangePattern()),
+                () -> assertNull(thymeleafEndpoint.getOrder()),
+                () -> assertNull(thymeleafEndpoint.getPrefix()),
+                () -> assertEquals(ThymeleafResolverType.CLASS_LOADER, thymeleafEndpoint.getResolver()),
+                () -> assertNull(thymeleafEndpoint.getSuffix()),
+                () -> assertNotNull(thymeleafEndpoint.getTemplateEngine()),
+                () -> assertNull(thymeleafEndpoint.getTemplateMode()));
+
+        assertEquals(1, thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().size());
+        ITemplateResolver resolver = thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().stream().findFirst().get();
+        assertTrue(resolver instanceof ClassLoaderTemplateResolver);
+
+        ClassLoaderTemplateResolver templateResolver = (ClassLoaderTemplateResolver) resolver;
+        assertAll("templateResolver",
+                () -> assertTrue(templateResolver.isCacheable()),
+                () -> assertNull(templateResolver.getCacheTTLMs()),
+                () -> assertNull(templateResolver.getCharacterEncoding()),
+                () -> assertFalse(templateResolver.getCheckExistence()),
+                () -> assertNull(templateResolver.getOrder()),
+                () -> assertNull(templateResolver.getPrefix()),
+                () -> assertNull(templateResolver.getSuffix()),
+                () -> assertEquals(TemplateMode.HTML, templateResolver.getTemplateMode()));
+    }
 
     @Override
     protected RouteBuilder createRouteBuilder() {
@@ -32,13 +92,15 @@ public class ThymeleafEndpointTest extends ThymeleafTest {
 
                 ThymeleafEndpoint endpoint = new ThymeleafEndpoint();
                 endpoint.setCamelContext(context);
-                endpoint.setAllowTemplateFromHeader(true);
                 endpoint.setAllowContextMapAll(true);
-                endpoint.setResourceUri("org/apache/camel/component/thymeleaf/example.txt");
+                endpoint.setResourceUri("org/apache/camel/component/thymeleaf/letter.txt");
 
-                context.addEndpoint("free", endpoint);
+                context.addEndpoint(TEST_ENDPOINT, endpoint);
 
-                from("direct:a").to("free");
+                from(DIRECT_START)
+                        .setBody(simple(SPAZZ_TESTING_SERVICE))
+                        .to(TEST_ENDPOINT)
+                        .to(MOCK_RESULT);
             }
         };
     }
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafFileResolverAllParamsTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafFileResolverAllParamsTest.java
new file mode 100644
index 00000000000..612c84bd962
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafFileResolverAllParamsTest.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.FileTemplateResolver;
+import org.thymeleaf.templateresolver.ITemplateResolver;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class ThymeleafFileResolverAllParamsTest extends ThymeleafAbstractBaseTest {
+
+    @Test
+    public void testThymeleaf() throws InterruptedException {
+
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedMessageCount(1);
+        mock.message(0).body().contains(THANK_YOU_FOR_YOUR_ORDER);
+        mock.message(0).body().endsWith(SPAZZ_TESTING_SERVICE);
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_TEMPLATE).isNull();
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_VARIABLE_MAP).isNull();
+        mock.message(0).header(FIRST_NAME).isEqualTo(JANE);
+
+        template.request(DIRECT_START, basicHeaderProcessor);
+
+        mock.assertIsSatisfied();
+
+        ThymeleafEndpoint thymeleafEndpoint = context.getEndpoint(
+                "thymeleaf:org/apache/camel/component/thymeleaf/letter?allowContextMapAll=true&cacheTimeToLive=500&cacheable=false&checkExistence=true&encoding=UTF-8&order=1&prefix=src/test/resources/&templateMode=HTML&resolver=FILE&suffix=.html",
+                ThymeleafEndpoint.class);
+
+        assertAll("properties",
+                () -> assertNotNull(thymeleafEndpoint),
+                () -> assertTrue(thymeleafEndpoint.isAllowContextMapAll()),
+                () -> assertFalse(thymeleafEndpoint.getCacheable()),
+                () -> assertEquals(CACHE_TIME_TO_LIVE, thymeleafEndpoint.getCacheTimeToLive()),
+                () -> assertTrue(thymeleafEndpoint.getCheckExistence()),
+                () -> assertEquals(UTF_8_ENCODING, thymeleafEndpoint.getEncoding()),
+                () -> assertEquals(ExchangePattern.InOut, thymeleafEndpoint.getExchangePattern()),
+                () -> assertEquals(ORDER, thymeleafEndpoint.getOrder()),
+                () -> assertEquals(PREFIX_SRC_TEST_RESOURCES, thymeleafEndpoint.getPrefix()),
+                () -> assertEquals(ThymeleafResolverType.FILE, thymeleafEndpoint.getResolver()),
+                () -> assertEquals(HTML_SUFFIX, thymeleafEndpoint.getSuffix()),
+                () -> assertNotNull(thymeleafEndpoint.getTemplateEngine()),
+                () -> assertEquals(HTML, thymeleafEndpoint.getTemplateMode()));
+
+        assertEquals(1, thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().size());
+        ITemplateResolver resolver = thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().stream().findFirst().get();
+        assertTrue(resolver instanceof FileTemplateResolver);
+
+        FileTemplateResolver templateResolver = (FileTemplateResolver) resolver;
+        assertAll("templateResolver",
+                () -> assertFalse(templateResolver.isCacheable()),
+                () -> assertEquals(CACHE_TIME_TO_LIVE, templateResolver.getCacheTTLMs()),
+                () -> assertEquals(UTF_8_ENCODING, templateResolver.getCharacterEncoding()),
+                () -> assertTrue(templateResolver.getCheckExistence()),
+                () -> assertEquals(ORDER, templateResolver.getOrder()),
+                () -> assertEquals(PREFIX_SRC_TEST_RESOURCES, templateResolver.getPrefix()),
+                () -> assertEquals(HTML_SUFFIX, templateResolver.getSuffix()),
+                () -> assertEquals(TemplateMode.HTML, templateResolver.getTemplateMode()));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+
+                context.setTracing(true);
+                from(DIRECT_START)
+                        .setBody(simple(SPAZZ_TESTING_SERVICE))
+                        .to("thymeleaf:org/apache/camel/component/thymeleaf/letter?allowContextMapAll=true&cacheTimeToLive=500&cacheable=false&checkExistence=true&encoding=UTF-8&order=1&prefix=src/test/resources/&templateMode=HTML&resolver=FILE&suffix=.html")
+                        .to(MOCK_RESULT);
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafFileResolverTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafFileResolverTest.java
new file mode 100644
index 00000000000..9b034325ebc
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafFileResolverTest.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.FileTemplateResolver;
+import org.thymeleaf.templateresolver.ITemplateResolver;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class ThymeleafFileResolverTest extends ThymeleafAbstractBaseTest {
+
+    @Test
+    public void testThymeleaf() throws InterruptedException {
+
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedMessageCount(1);
+        mock.message(0).body().contains(THANK_YOU_FOR_YOUR_ORDER);
+        mock.message(0).body().endsWith(SPAZZ_TESTING_SERVICE);
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_TEMPLATE).isNull();
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_VARIABLE_MAP).isNull();
+        mock.message(0).header(FIRST_NAME).isEqualTo(JANE);
+
+        template.request(DIRECT_START, basicHeaderProcessor);
+
+        mock.assertIsSatisfied();
+
+        ThymeleafEndpoint thymeleafEndpoint = context.getEndpoint(
+                "thymeleaf:src/test/resources/org/apache/camel/component/thymeleaf/letter.html?allowContextMapAll=true&resolver=FILE",
+                ThymeleafEndpoint.class);
+
+        assertAll("properties",
+                () -> assertNotNull(thymeleafEndpoint),
+                () -> assertTrue(thymeleafEndpoint.isAllowContextMapAll()),
+                () -> assertNull(thymeleafEndpoint.getCacheable()),
+                () -> assertNull(thymeleafEndpoint.getCacheTimeToLive()),
+                () -> assertNull(thymeleafEndpoint.getCheckExistence()),
+                () -> assertNull(thymeleafEndpoint.getEncoding()),
+                () -> assertEquals(ExchangePattern.InOut, thymeleafEndpoint.getExchangePattern()),
+                () -> assertNull(thymeleafEndpoint.getOrder()),
+                () -> assertNull(thymeleafEndpoint.getPrefix()),
+                () -> assertEquals(ThymeleafResolverType.FILE, thymeleafEndpoint.getResolver()),
+                () -> assertNull(thymeleafEndpoint.getSuffix()),
+                () -> assertNotNull(thymeleafEndpoint.getTemplateEngine()),
+                () -> assertNull(thymeleafEndpoint.getTemplateMode()));
+
+        assertEquals(1, thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().size());
+        ITemplateResolver resolver = thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().stream().findFirst().get();
+        assertTrue(resolver instanceof FileTemplateResolver);
+
+        FileTemplateResolver templateResolver = (FileTemplateResolver) resolver;
+        assertAll("templateResolver",
+                () -> assertTrue(templateResolver.isCacheable()),
+                () -> assertNull(templateResolver.getCacheTTLMs()),
+                () -> assertNull(templateResolver.getCharacterEncoding()),
+                () -> assertFalse(templateResolver.getCheckExistence()),
+                () -> assertNull(templateResolver.getOrder()),
+                () -> assertNull(templateResolver.getPrefix()),
+                () -> assertNull(templateResolver.getSuffix()),
+                () -> assertEquals(TemplateMode.HTML, templateResolver.getTemplateMode()));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+
+                from(DIRECT_START)
+                        .setBody(simple(SPAZZ_TESTING_SERVICE))
+                        .to("thymeleaf:src/test/resources/org/apache/camel/component/thymeleaf/letter.html?allowContextMapAll=true&resolver=FILE")
+                        .to(MOCK_RESULT);
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafLetterWithoutHeaderTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafLetterWithoutHeaderTest.java
deleted file mode 100644
index c3dd7016f46..00000000000
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafLetterWithoutHeaderTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.thymeleaf;
-
-import org.apache.camel.builder.RouteBuilder;
-
-public class ThymeleafLetterWithoutHeaderTest extends ThymeleafLetterTest {
-
-    @Override
-    protected RouteBuilder createRouteBuilder() {
-
-        return new RouteBuilder() {
-
-            public void configure() {
-
-                from("direct:a").to("thymeleaf:org/apache/camel/component/thymeleaf/header.txt")
-                        .to("thymeleaf:org/apache/camel/component/thymeleaf/letterWithoutHeader.txt").to("mock:result");
-            }
-        };
-    }
-
-}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafOverrideHeaderTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafOverrideHeaderTest.java
deleted file mode 100644
index ffbf076fec0..00000000000
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafOverrideHeaderTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.thymeleaf;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.test.junit5.CamelTestSupport;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-public class ThymeleafOverrideHeaderTest extends CamelTestSupport {
-
-    @Override
-    public boolean isUseRouteBuilder() {
-
-        return false;
-    }
-
-    private Exchange createLetter() {
-
-        Exchange exchange = context.getEndpoint("direct:a").createExchange();
-
-        Message msg = exchange.getIn();
-        msg.setHeader("firstName", "Claus");
-        msg.setHeader("lastName", "Ibsen");
-        msg.setHeader("item", "Camel in Action");
-        msg.setBody("PS: Next beer is on me, James");
-        msg.setHeader(ThymeleafConstants.THYMELEAF_RESOURCE_URI, "org/apache/camel/component/thymeleaf/letter.txt");
-        return exchange;
-    }
-
-    @Test
-    public void testThymeleafLetter() throws Exception {
-
-        context.addRoutes(new RouteBuilder() {
-
-            @Override
-            public void configure() {
-
-                from("direct:a")
-                        .to("thymeleaf:org/apache/camel/component/thymeleaf/example.txt")
-                        .to("mock:result");
-            }
-        });
-        context.start();
-
-        Exchange out = template.send("direct:a", createLetter());
-        assertTrue(out.isFailed());
-
-        context.stop();
-    }
-
-    @Test
-    public void testThymeleafLetterAllowed() throws Exception {
-
-        context.addRoutes(new RouteBuilder() {
-
-            @Override
-            public void configure() {
-
-                from("direct:a")
-                        .to("thymeleaf:org/apache/camel/component/thymeleaf/example.txt?allowTemplateFromHeader=true")
-                        .to("mock:result");
-            }
-        });
-        context.start();
-
-        MockEndpoint mock = getMockEndpoint("mock:result");
-        mock.expectedMessageCount(1);
-        mock.message(0).body().contains("Dear Ibsen, Claus");
-        mock.message(0).body().contains("Thanks for the order of Camel in Action.");
-
-        template.send("direct:a", createLetter());
-
-        mock.assertIsSatisfied();
-
-        context.stop();
-    }
-
-}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafEncodingTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafResourceUriTest.java
similarity index 53%
rename from components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafEncodingTest.java
rename to components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafResourceUriTest.java
index ee43bea9aeb..0d3463a04eb 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafEncodingTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafResourceUriTest.java
@@ -17,8 +17,25 @@
 package org.apache.camel.component.thymeleaf;
 
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
 
-public class ThymeleafEncodingTest extends ThymeleafLetterTest {
+public class ThymeleafResourceUriTest extends ThymeleafAbstractBaseTest {
+
+    @Test
+    public void testThymeleaf() throws InterruptedException {
+
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedMessageCount(1);
+        mock.message(0).body().contains(THANK_YOU_FOR_YOUR_ORDER);
+        mock.message(0).body().endsWith(SPAZZ_TESTING_SERVICE);
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_TEMPLATE).isNull();
+        mock.message(0).header(FIRST_NAME).isEqualTo(JANE);
+
+        template.request(DIRECT_START, resourceUriHeaderProcessor);
+
+        mock.assertIsSatisfied();
+    }
 
     @Override
     protected RouteBuilder createRouteBuilder() {
@@ -27,8 +44,10 @@ public class ThymeleafEncodingTest extends ThymeleafLetterTest {
 
             public void configure() {
 
-                from("direct:a").to("thymeleaf:org/apache/camel/component/thymeleaf/letter-utf16.txt?encoding=UTF-16")
-                        .to("mock:result");
+                from(DIRECT_START)
+                        .setBody(simple(SPAZZ_TESTING_SERVICE))
+                        .to("thymeleaf:dontcare?allowContextMapAll=true&resolver=CLASS_LOADER")
+                        .to(MOCK_RESULT);
             }
         };
     }
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafSetHeaderTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafSetHeaderTest.java
index b65a134160f..34519fb6057 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafSetHeaderTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafSetHeaderTest.java
@@ -16,9 +16,7 @@
  */
 package org.apache.camel.component.thymeleaf;
 
-import org.apache.camel.Exchange;
 import org.apache.camel.Message;
-import org.apache.camel.Processor;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.test.spring.junit5.CamelSpringTestSupport;
 import org.junit.jupiter.api.Test;
@@ -33,7 +31,7 @@ public class ThymeleafSetHeaderTest extends CamelSpringTestSupport {
     }
 
     @Test
-    public void testSendingOrgane() throws Exception {
+    public void testSendingOrange() throws Exception {
 
         assertRespondsWith("orange", "I am an orange");
     }
@@ -42,15 +40,12 @@ public class ThymeleafSetHeaderTest extends CamelSpringTestSupport {
 
         MockEndpoint mock = getMockEndpoint("mock:result");
         mock.expectedMessageCount(1);
-        //mock.expectedHeaderReceived("fruit", value);
-        mock.expectedBodiesReceived(expectedBody);
-        template.request("direct:start", new Processor() {
+        mock.expectedHeaderReceived("fruit", value);
+        mock.expectedBodyReceived().body().endsWith(expectedBody);
+        template.request("direct:start", exchange -> {
 
-            public void process(Exchange exchange) {
-
-                Message in = exchange.getIn();
-                in.setBody(value);
-            }
+            Message in = exchange.getIn();
+            in.setBody(value);
         });
         mock.assertIsSatisfied();
     }
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafStringResolverAllParamsTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafStringResolverAllParamsTest.java
new file mode 100644
index 00000000000..e9f89f641e1
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafStringResolverAllParamsTest.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.ITemplateResolver;
+import org.thymeleaf.templateresolver.StringTemplateResolver;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class ThymeleafStringResolverAllParamsTest extends ThymeleafAbstractBaseTest {
+
+    @Test
+    public void testThymeleaf() throws InterruptedException {
+
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedMessageCount(1);
+        mock.message(0).body().contains(THANK_YOU_FOR_YOUR_ORDER);
+        mock.message(0).body().endsWith(SPAZZ_TESTING_SERVICE);
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_TEMPLATE).isNull();
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_VARIABLE_MAP).isNull();
+        mock.message(0).header(FIRST_NAME).isEqualTo(JANE);
+
+        template.request(DIRECT_START, templateHeaderProcessor);
+
+        mock.assertIsSatisfied();
+
+        ThymeleafEndpoint thymeleafEndpoint = context.getEndpoint(
+                "thymeleaf:dontcare?cacheable=true&cacheTimeToLive=500&checkExistence=true&order=1&allowContextMapAll=true&resolver=STRING",
+                ThymeleafEndpoint.class);
+
+        assertAll("properties",
+                () -> assertNotNull(thymeleafEndpoint),
+                () -> assertTrue(thymeleafEndpoint.isAllowContextMapAll()),
+                () -> assertTrue(thymeleafEndpoint.getCacheable()),
+                () -> assertEquals(CACHE_TIME_TO_LIVE, thymeleafEndpoint.getCacheTimeToLive()),
+                () -> assertTrue(thymeleafEndpoint.getCheckExistence()),
+                () -> assertNull(thymeleafEndpoint.getEncoding()),
+                () -> assertEquals(ExchangePattern.InOut, thymeleafEndpoint.getExchangePattern()),
+                () -> assertEquals(ORDER, thymeleafEndpoint.getOrder()),
+                () -> assertNull(thymeleafEndpoint.getPrefix()),
+                () -> assertEquals(ThymeleafResolverType.STRING, thymeleafEndpoint.getResolver()),
+                () -> assertNull(thymeleafEndpoint.getSuffix()),
+                () -> assertNotNull(thymeleafEndpoint.getTemplateEngine()),
+                () -> assertNull(thymeleafEndpoint.getTemplateMode()));
+
+        assertEquals(1, thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().size());
+        ITemplateResolver resolver = thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().stream().findFirst().get();
+        assertTrue(resolver instanceof StringTemplateResolver);
+
+        StringTemplateResolver templateResolver = (StringTemplateResolver) resolver;
+        assertAll("templateResolver",
+                () -> assertTrue(templateResolver.isCacheable()),
+                () -> assertEquals(CACHE_TIME_TO_LIVE, templateResolver.getCacheTTLMs()),
+                () -> assertTrue(templateResolver.getCheckExistence()),
+                () -> assertEquals(ORDER, templateResolver.getOrder()),
+                () -> assertEquals(TemplateMode.HTML, templateResolver.getTemplateMode()));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+
+                from(DIRECT_START)
+                        .setBody(simple(SPAZZ_TESTING_SERVICE))
+                        .to("thymeleaf:dontcare?cacheable=true&cacheTimeToLive=500&checkExistence=true&order=1&allowContextMapAll=true&resolver=STRING")
+                        .to(MOCK_RESULT);
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafStringResolverTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafStringResolverTest.java
new file mode 100644
index 00000000000..1ca56bdc6df
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafStringResolverTest.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.component.thymeleaf;
+
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.ITemplateResolver;
+import org.thymeleaf.templateresolver.StringTemplateResolver;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class ThymeleafStringResolverTest extends ThymeleafAbstractBaseTest {
+
+    @Test
+    public void testThymeleaf() throws InterruptedException {
+
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedMessageCount(1);
+        mock.message(0).body().contains(THANK_YOU_FOR_YOUR_ORDER);
+        mock.message(0).body().endsWith(SPAZZ_TESTING_SERVICE);
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_TEMPLATE).isNull();
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_VARIABLE_MAP).isNull();
+        mock.message(0).header(FIRST_NAME).isEqualTo(JANE);
+
+        template.request(DIRECT_START, templateHeaderProcessor);
+
+        mock.assertIsSatisfied();
+
+        ThymeleafEndpoint thymeleafEndpoint = context.getEndpoint(
+                "thymeleaf:dontcare?templateMode=HTML&allowContextMapAll=true&resolver=STRING",
+                ThymeleafEndpoint.class);
+
+        assertAll("properties",
+                () -> assertNotNull(thymeleafEndpoint),
+                () -> assertTrue(thymeleafEndpoint.isAllowContextMapAll()),
+                () -> assertNull(thymeleafEndpoint.getCacheable()),
+                () -> assertNull(thymeleafEndpoint.getCacheTimeToLive()),
+                () -> assertNull(thymeleafEndpoint.getCheckExistence()),
+                () -> assertNull(thymeleafEndpoint.getEncoding()),
+                () -> assertEquals(ExchangePattern.InOut, thymeleafEndpoint.getExchangePattern()),
+                () -> assertNull(thymeleafEndpoint.getOrder()),
+                () -> assertNull(thymeleafEndpoint.getPrefix()),
+                () -> assertEquals(ThymeleafResolverType.STRING, thymeleafEndpoint.getResolver()),
+                () -> assertNull(thymeleafEndpoint.getSuffix()),
+                () -> assertNotNull(thymeleafEndpoint.getTemplateEngine()),
+                () -> assertEquals(HTML, thymeleafEndpoint.getTemplateMode()));
+
+        assertEquals(1, thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().size());
+        ITemplateResolver resolver = thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().stream().findFirst().get();
+        assertTrue(resolver instanceof StringTemplateResolver);
+
+        StringTemplateResolver templateResolver = (StringTemplateResolver) resolver;
+        assertAll("templateResolver",
+                () -> assertFalse(templateResolver.isCacheable()),
+                () -> assertNull(templateResolver.getCacheTTLMs()),
+                () -> assertFalse(templateResolver.getCheckExistence()),
+                () -> assertNull(templateResolver.getOrder()),
+                () -> assertEquals(TemplateMode.HTML, templateResolver.getTemplateMode()));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+
+                from(DIRECT_START)
+                        .setBody(simple(SPAZZ_TESTING_SERVICE))
+                        .to("thymeleaf:dontcare?templateMode=HTML&allowContextMapAll=true&resolver=STRING")
+                        .to(MOCK_RESULT);
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafLetterTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafTemplateAsHeaderTest.java
similarity index 51%
rename from components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafLetterTest.java
rename to components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafTemplateAsHeaderTest.java
index 361d49a052d..79d41afcdde 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafLetterTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafTemplateAsHeaderTest.java
@@ -16,41 +16,24 @@
  */
 package org.apache.camel.component.thymeleaf;
 
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.test.junit5.CamelTestSupport;
 import org.junit.jupiter.api.Test;
 
-/**
- * Unit test for wiki documentation
- */
-public class ThymeleafLetterTest extends CamelTestSupport {
-
-    // START SNIPPET: e1
-    private Exchange createLetter() {
-
-        Exchange exchange = context.getEndpoint("direct:a").createExchange();
-
-        Message msg = exchange.getIn();
-        msg.setHeader("firstName", "Claus");
-        msg.setHeader("lastName", "Ibsen");
-        msg.setHeader("item", "Camel in Action");
-        msg.setBody("PS: Next beer is on me, James");
-
-        return exchange;
-    }
+public class ThymeleafTemplateAsHeaderTest extends ThymeleafAbstractBaseTest {
 
     @Test
-    public void testThymeleafLetter() throws Exception {
+    public void testThymeleaf() throws InterruptedException {
 
-        MockEndpoint mock = getMockEndpoint("mock:result");
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
         mock.expectedMessageCount(1);
-        mock.message(0).body().contains("Dear Ibsen, Claus");
-        mock.message(0).body().contains("Thanks for the order of Camel in Action.");
+        mock.message(0).body().contains(THANK_YOU_FOR_YOUR_ORDER);
+        mock.message(0).body().endsWith(SPAZZ_TESTING_SERVICE);
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_TEMPLATE).isNull();
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_VARIABLE_MAP).isNull();
+        mock.message(0).header(FIRST_NAME).isEqualTo(JANE);
 
-        template.send("direct:a", createLetter());
+        template.request(DIRECT_START, templateHeaderProcessor);
 
         mock.assertIsSatisfied();
     }
@@ -61,13 +44,13 @@ public class ThymeleafLetterTest extends CamelTestSupport {
         return new RouteBuilder() {
 
             public void configure() {
-                context.setTracing(true);
 
-                from("direct:a")
-                        .to("thymeleaf:org/apache/camel/component/thymeleaf/letter.txt")
-                        .to("mock:result");
+                from(DIRECT_START)
+                        .setBody(simple(SPAZZ_TESTING_SERVICE))
+                        .to("thymeleaf:dontcare?templateMode=HTML&allowContextMapAll=true&resolver=DEFAULT")
+                        .to(MOCK_RESULT);
             }
         };
     }
-    // END SNIPPET: e1
+
 }
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafTemplateInHeaderTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafTemplateInHeaderTest.java
deleted file mode 100644
index 60842117bbc..00000000000
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafTemplateInHeaderTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.thymeleaf;
-
-import java.util.Map.Entry;
-import java.util.Set;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.InvalidPayloadException;
-import org.apache.camel.Message;
-import org.apache.camel.Processor;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.test.junit5.CamelTestSupport;
-import org.junit.jupiter.api.Test;
-
-import static org.apache.camel.test.junit5.TestSupport.assertMessageBodyEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-public class ThymeleafTemplateInHeaderTest extends CamelTestSupport {
-
-    @Test
-    public void testReceivesFooResponse() throws Exception {
-
-        assertRespondsWith("cheese", "foo", "<hello>foo</hello>");
-    }
-
-    @Test
-    public void testReceivesBarResponse() throws Exception {
-
-        assertRespondsWith("cheese", "bar", "<hello>bar</hello>");
-    }
-
-    @Test
-    public void testRespectHeaderNamesUpperCase() throws Exception {
-
-        assertRespondsWith("Cheese", "bar", "<hello>bar</hello>");
-    }
-
-    @Test
-    public void testRespectHeaderNamesCamelCase() throws Exception {
-
-        assertRespondsWith("CorrelationID", "bar", "<hello>bar</hello>");
-    }
-
-    protected void assertRespondsWith(final String headerName, final String headerValue, String expectedBody)
-            throws InvalidPayloadException {
-
-        Exchange response = template.request("direct:a", new Processor() {
-
-            public void process(Exchange exchange) {
-
-                Message in = exchange.getIn();
-                in.setHeader(ThymeleafConstants.THYMELEAF_TEMPLATE, "<hello>${headers." + headerName + "}</hello>");
-                in.setHeader(headerName, headerValue);
-            }
-        });
-        assertMessageBodyEquals(response, expectedBody);
-
-        Object template = response.getMessage().getHeader(ThymeleafConstants.THYMELEAF_TEMPLATE);
-        assertNull(template, "Template header should have been removed");
-
-        Set<Entry<String, Object>> entrySet = response.getMessage().getHeaders().entrySet();
-        boolean keyFound = false;
-        for (Entry<String, Object> entry : entrySet) {
-            if (entry.getKey().equals(headerName)) {
-                keyFound = true;
-                break;
-            }
-        }
-        assertTrue(keyFound, "Header should been found");
-    }
-
-    @Override
-    protected RouteBuilder createRouteBuilder() {
-
-        return new RouteBuilder() {
-
-            public void configure() {
-
-                from("direct:a").to("thymeleaf://dummy?allowTemplateFromHeader=true");
-            }
-        };
-    }
-
-}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafTest.java
deleted file mode 100644
index 852520813e6..00000000000
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.thymeleaf;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Processor;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.test.junit5.CamelTestSupport;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-/**
- * Thymeleaf unit test
- */
-public class ThymeleafTest extends CamelTestSupport {
-
-    @Test
-    public void testThymeleafLetter() {
-
-        Exchange exchange = template.request("direct:a", new Processor() {
-
-            @Override
-            public void process(Exchange exchange) {
-
-                exchange.getIn().setBody("Monday");
-                exchange.getIn().setHeader("name", "Christian");
-                exchange.setProperty("item", "7");
-            }
-        });
-
-        assertEquals("Dear Christian. You ordered item 7 on Monday.", exchange.getMessage().getBody());
-        assertEquals("Christian", exchange.getMessage().getHeader("name"));
-    }
-
-    @Test
-    public void testThymeleafDataModel() {
-
-        Exchange exchange = template.request("direct:a", new Processor() {
-
-            @Override
-            public void process(Exchange exchange) {
-
-                exchange.getIn().setBody("");
-                exchange.getIn().setHeader("name", "Christian");
-                Map<String, Object> variableMap = new HashMap<>();
-                Map<String, Object> headersMap = new HashMap<>();
-                headersMap.put("name", "Willem");
-                variableMap.put("headers", headersMap);
-                variableMap.put("body", "Monday");
-                variableMap.put("exchange", exchange);
-                exchange.getIn().setHeader(ThymeleafConstants.THYMELEAF_VARIABLE_MAP, variableMap);
-                exchange.setProperty("item", "7");
-            }
-        });
-
-        assertEquals("Dear Willem. You ordered item 7 on Monday.", exchange.getMessage().getBody());
-        assertEquals("Christian", exchange.getMessage().getHeader("name"));
-    }
-
-    @Override
-    protected RouteBuilder createRouteBuilder() {
-
-        return new RouteBuilder() {
-
-            public void configure() {
-                // START SNIPPET: example
-                from("direct:a").to(
-                        "thymeleaf:org/apache/camel/component/thymeleaf/example.txt?allowTemplateFromHeader=true&allowContextMapAll=true");
-                // END SNIPPET: example
-            }
-        };
-    }
-
-}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafUrlResolverAllParamsTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafUrlResolverAllParamsTest.java
new file mode 100644
index 00000000000..50040e44253
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafUrlResolverAllParamsTest.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import com.github.tomakehurst.wiremock.junit5.WireMockTest;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.ITemplateResolver;
+import org.thymeleaf.templateresolver.UrlTemplateResolver;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.ok;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@WireMockTest(httpPort = 9843)
+public class ThymeleafUrlResolverAllParamsTest extends ThymeleafAbstractBaseTest {
+
+    @Test
+    public void testThymeleaf() throws InterruptedException {
+
+        stubFor(get("/dontcare.html").willReturn(ok(fragment())));
+
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedMessageCount(1);
+        mock.message(0).body().contains(YOU_WILL_NOTIFIED);
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_TEMPLATE).isNull();
+        mock.message(0).header(FIRST_NAME).isEqualTo(JANE);
+
+        template.request(DIRECT_START, urlTemplateHeaderProcessor);
+
+        mock.assertIsSatisfied();
+
+        ThymeleafEndpoint thymeleafEndpoint = context.getEndpoint(
+                "thymeleaf:dontcare?allowContextMapAll=true&cacheTimeToLive=500&cacheable=false&encoding=UTF-8&order=1&prefix=&suffix=.html&resolver=URL&templateMode=HTML",
+                ThymeleafEndpoint.class);
+
+        assertAll("properties",
+                () -> assertNotNull(thymeleafEndpoint),
+                () -> assertTrue(thymeleafEndpoint.isAllowContextMapAll()),
+                () -> assertFalse(thymeleafEndpoint.getCacheable()),
+                () -> assertEquals(CACHE_TIME_TO_LIVE, thymeleafEndpoint.getCacheTimeToLive()),
+                () -> assertNull(thymeleafEndpoint.getCheckExistence()),
+                () -> assertEquals(UTF_8_ENCODING, thymeleafEndpoint.getEncoding()),
+                () -> assertEquals(ExchangePattern.InOut, thymeleafEndpoint.getExchangePattern()),
+                () -> assertEquals(ORDER, thymeleafEndpoint.getOrder()),
+                () -> assertEquals("", thymeleafEndpoint.getPrefix()),
+                () -> assertEquals(ThymeleafResolverType.URL, thymeleafEndpoint.getResolver()),
+                () -> assertEquals(HTML_SUFFIX, thymeleafEndpoint.getSuffix()),
+                () -> assertNotNull(thymeleafEndpoint.getTemplateEngine()),
+                () -> assertEquals(HTML, thymeleafEndpoint.getTemplateMode()));
+
+        assertEquals(1, thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().size());
+        ITemplateResolver resolver = thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().stream().findFirst().get();
+        assertTrue(resolver instanceof UrlTemplateResolver);
+
+        UrlTemplateResolver templateResolver = (UrlTemplateResolver) resolver;
+        assertAll("templateResolver",
+                () -> assertFalse(templateResolver.isCacheable()),
+                () -> assertEquals(CACHE_TIME_TO_LIVE, templateResolver.getCacheTTLMs()),
+                () -> assertEquals(UTF_8_ENCODING, templateResolver.getCharacterEncoding()),
+                () -> assertFalse(templateResolver.getCheckExistence()),
+                () -> assertEquals(ORDER, templateResolver.getOrder()),
+                () -> assertEquals("", templateResolver.getPrefix()),
+                () -> assertEquals(HTML_SUFFIX, templateResolver.getSuffix()),
+                () -> assertEquals(TemplateMode.HTML, templateResolver.getTemplateMode()));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+
+                from(DIRECT_START)
+                        .to("thymeleaf:dontcare?allowContextMapAll=true&cacheTimeToLive=500&cacheable=false&encoding=UTF-8&order=1&prefix=&suffix=.html&resolver=URL&templateMode=HTML")
+                        .to(MOCK_RESULT);
+            }
+        };
+    }
+
+    protected String fragment() {
+
+        return """
+                <span th:fragment="test" th:remove="tag">
+                You will be notified when your order ships.
+                </span>
+                """;
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafUrlResolverTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafUrlResolverTest.java
new file mode 100644
index 00000000000..9e4ea6531f5
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafUrlResolverTest.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import com.github.tomakehurst.wiremock.junit5.WireMockTest;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.ITemplateResolver;
+import org.thymeleaf.templateresolver.UrlTemplateResolver;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.ok;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@WireMockTest(httpPort = 9843)
+public class ThymeleafUrlResolverTest extends ThymeleafAbstractBaseTest {
+
+    @Test
+    public void testThymeleaf() throws InterruptedException {
+
+        stubFor(get("/dontcare.html").willReturn(ok(fragment())));
+
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedMessageCount(1);
+        mock.message(0).body().contains(YOU_WILL_NOTIFIED);
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_TEMPLATE).isNull();
+        mock.message(0).header(FIRST_NAME).isEqualTo(JANE);
+
+        template.request(DIRECT_START, urlTemplateHeaderProcessor);
+
+        mock.assertIsSatisfied();
+
+        ThymeleafEndpoint thymeleafEndpoint = context.getEndpoint(
+                "thymeleaf:dontcare?allowContextMapAll=true&resolver=URL",
+                ThymeleafEndpoint.class);
+
+        assertAll("properties",
+                () -> assertNotNull(thymeleafEndpoint),
+                () -> assertTrue(thymeleafEndpoint.isAllowContextMapAll()),
+                () -> assertNull(thymeleafEndpoint.getCacheable()),
+                () -> assertNull(thymeleafEndpoint.getCacheTimeToLive()),
+                () -> assertNull(thymeleafEndpoint.getCheckExistence()),
+                () -> assertNull(thymeleafEndpoint.getEncoding()),
+                () -> assertEquals(ExchangePattern.InOut, thymeleafEndpoint.getExchangePattern()),
+                () -> assertNull(thymeleafEndpoint.getOrder()),
+                () -> assertNull(thymeleafEndpoint.getPrefix()),
+                () -> assertEquals(ThymeleafResolverType.URL, thymeleafEndpoint.getResolver()),
+                () -> assertNull(thymeleafEndpoint.getSuffix()),
+                () -> assertNotNull(thymeleafEndpoint.getTemplateEngine()),
+                () -> assertNull(thymeleafEndpoint.getTemplateMode()));
+
+        assertEquals(1, thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().size());
+        ITemplateResolver resolver = thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().stream().findFirst().get();
+        assertTrue(resolver instanceof UrlTemplateResolver);
+
+        UrlTemplateResolver templateResolver = (UrlTemplateResolver) resolver;
+        assertAll("templateResolver",
+                () -> assertTrue(templateResolver.isCacheable()),
+                () -> assertNull(templateResolver.getCacheTTLMs()),
+                () -> assertNull(templateResolver.getCharacterEncoding()),
+                () -> assertFalse(templateResolver.getCheckExistence()),
+                () -> assertNull(templateResolver.getOrder()),
+                () -> assertNull(templateResolver.getPrefix()),
+                () -> assertNull(templateResolver.getSuffix()),
+                () -> assertEquals(TemplateMode.HTML, templateResolver.getTemplateMode()));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+
+                from(DIRECT_START)
+                        .to("thymeleaf:dontcare?allowContextMapAll=true&resolver=URL")
+                        .to(MOCK_RESULT);
+            }
+        };
+    }
+
+    protected String fragment() {
+
+        return """
+                <span th:fragment="test" th:remove="tag">
+                You will be notified when your order ships.
+                </span>
+                """;
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafValuesInPropertiesTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafValuesInPropertiesTest.java
deleted file mode 100644
index 5183f3b5457..00000000000
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafValuesInPropertiesTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.thymeleaf;
-
-import org.apache.camel.EndpointInject;
-import org.apache.camel.Exchange;
-import org.apache.camel.Processor;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.test.junit5.CamelTestSupport;
-import org.junit.jupiter.api.Test;
-
-public class ThymeleafValuesInPropertiesTest extends CamelTestSupport {
-
-    @EndpointInject("mock:result")
-    private MockEndpoint mock;
-
-    @Test
-    public void testThymeleafLetter() throws Exception {
-
-        mock.expectedBodiesReceived("Dear Christian. You ordered item 7.");
-
-        template.send("direct:a", new Processor() {
-
-            @Override
-            public void process(Exchange exchange) {
-
-                exchange.getIn().setHeader(ThymeleafConstants.THYMELEAF_TEMPLATE,
-                        "Dear ${exchange.properties.name}. You ordered item ${exchange.properties.item}.");
-                exchange.setProperty("name", "Christian");
-                exchange.setProperty("item", "7");
-            }
-        });
-
-        mock.assertIsSatisfied();
-    }
-
-    @Override
-    protected RouteBuilder createRouteBuilder() {
-
-        return new RouteBuilder() {
-
-            public void configure() {
-
-                ThymeleafComponent fc = context.getComponent("thymeleaf", ThymeleafComponent.class);
-                fc.setAllowTemplateFromHeader(true);
-                fc.setAllowContextMapAll(true);
-
-                from("direct:a")
-                        .to("thymeleaf:dummy")
-                        .to("mock:result");
-            }
-        };
-    }
-
-}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafFileLetterTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafVariableMapHeaderTest.java
similarity index 51%
rename from components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafFileLetterTest.java
rename to components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafVariableMapHeaderTest.java
index 977a2778975..a8515332d3b 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafFileLetterTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafVariableMapHeaderTest.java
@@ -17,8 +17,26 @@
 package org.apache.camel.component.thymeleaf;
 
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
 
-public class ThymeleafFileLetterTest extends ThymeleafLetterTest {
+public class ThymeleafVariableMapHeaderTest extends ThymeleafAbstractBaseTest {
+
+    @Test
+    public void testThymeleaf() throws InterruptedException {
+
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedMessageCount(1);
+        mock.message(0).body().contains(THANK_YOU_FOR_YOUR_ORDER);
+        mock.message(0).body().endsWith(SPAZZ_TESTING_SERVICE);
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_TEMPLATE).isNull();
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_VARIABLE_MAP).isNull();
+        mock.message(0).header(FIRST_NAME).isNull();
+
+        template.request(DIRECT_START, variableMapHeaderProcessor);
+
+        mock.assertIsSatisfied();
+    }
 
     @Override
     protected RouteBuilder createRouteBuilder() {
@@ -27,9 +45,10 @@ public class ThymeleafFileLetterTest extends ThymeleafLetterTest {
 
             public void configure() {
 
-                from("direct:a")
-                        .to("thymeleaf:file:src/test/resources/org/apache/camel/component/thymeleaf/letter.txt")
-                        .to("mock:result");
+                from(DIRECT_START)
+                        .setBody(simple(SPAZZ_TESTING_SERVICE))
+                        .to("thymeleaf:dontcare?templateMode=HTML&resolver=DEFAULT")
+                        .to(MOCK_RESULT);
             }
         };
     }
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverAllParamsTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverAllParamsTest.java
new file mode 100644
index 00000000000..9be2eeb6179
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverAllParamsTest.java
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+
+import jakarta.servlet.ServletContext;
+
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.ITemplateResolver;
+import org.thymeleaf.templateresolver.WebApplicationTemplateResolver;
+import org.thymeleaf.web.servlet.JakartaServletWebApplication;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+
+public class ThymeleafWebApplicationResolverAllParamsTest extends ThymeleafAbstractBaseTest {
+
+    private static final String TEST_ENDPOINT = "testEndpoint";
+
+    private ServletContext servletContext;
+
+    private JakartaServletWebApplication jakartaServletWebApplication;
+
+    @BeforeEach
+    public void setUp() throws Exception {
+
+        super.setUp();
+
+        File initialFile = new File("src/test/resources/WEB-INF/templates/letter.html");
+        InputStream targetStream = FileUtils.openInputStream(initialFile);
+        Mockito.when(servletContext.getResourceAsStream(anyString())).thenReturn(targetStream);
+        Mockito.when(servletContext.getResource(anyString())).thenReturn(new URL("http://localhost/letter.html"));
+    }
+
+    @Test
+    public void testThymeleaf() throws InterruptedException {
+
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedMessageCount(1);
+        mock.message(0).body().contains(THANK_YOU_FOR_YOUR_ORDER);
+        mock.message(0).body().endsWith(SPAZZ_TESTING_SERVICE);
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_TEMPLATE).isNull();
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_VARIABLE_MAP).isNull();
+        mock.message(0).header(FIRST_NAME).isEqualTo(JANE);
+
+        template.request(DIRECT_START, basicHeaderProcessor);
+
+        mock.assertIsSatisfied();
+
+        ThymeleafEndpoint thymeleafEndpoint = context.getEndpoint(TEST_ENDPOINT, ThymeleafEndpoint.class);
+
+        assertAll("properties",
+                () -> assertNotNull(thymeleafEndpoint),
+                () -> assertTrue(thymeleafEndpoint.isAllowContextMapAll()),
+                () -> assertTrue(thymeleafEndpoint.getCacheable()),
+                () -> assertEquals(CACHE_TIME_TO_LIVE, thymeleafEndpoint.getCacheTimeToLive()),
+                () -> assertTrue(thymeleafEndpoint.getCheckExistence()),
+                () -> assertEquals(UTF_8_ENCODING, thymeleafEndpoint.getEncoding()),
+                () -> assertEquals(ExchangePattern.InOut, thymeleafEndpoint.getExchangePattern()),
+                () -> assertEquals(ORDER, thymeleafEndpoint.getOrder()),
+                () -> assertEquals(PREFIX_WEB_INF_TEMPLATES, thymeleafEndpoint.getPrefix()),
+                () -> assertEquals(ThymeleafResolverType.WEB_APP, thymeleafEndpoint.getResolver()),
+                () -> assertEquals(HTML_SUFFIX, thymeleafEndpoint.getSuffix()),
+                () -> assertNotNull(thymeleafEndpoint.getTemplateEngine()),
+                () -> assertEquals(HTML, thymeleafEndpoint.getTemplateMode()));
+
+        assertEquals(1, thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().size());
+        ITemplateResolver resolver = thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().stream().findFirst().get();
+        assertTrue(resolver instanceof WebApplicationTemplateResolver);
+
+        WebApplicationTemplateResolver templateResolver = (WebApplicationTemplateResolver) resolver;
+        assertAll("templateResolver",
+                () -> assertTrue(templateResolver.isCacheable()),
+                () -> assertEquals(CACHE_TIME_TO_LIVE, templateResolver.getCacheTTLMs()),
+                () -> assertEquals(UTF_8_ENCODING, templateResolver.getCharacterEncoding()),
+                () -> assertTrue(templateResolver.getCheckExistence()),
+                () -> assertEquals(ORDER, templateResolver.getOrder()),
+                () -> assertEquals(PREFIX_WEB_INF_TEMPLATES, templateResolver.getPrefix()),
+                () -> assertEquals(HTML_SUFFIX, templateResolver.getSuffix()),
+                () -> assertEquals(TemplateMode.HTML, templateResolver.getTemplateMode()));
+    }
+
+    private ServletContext servletContext() {
+
+        if (servletContext == null) {
+            servletContext = mock(ServletContext.class);
+        }
+
+        return servletContext;
+    }
+
+    private JakartaServletWebApplication jakartaServletWebApplication() {
+
+        if (jakartaServletWebApplication == null) {
+            jakartaServletWebApplication = JakartaServletWebApplication.buildApplication(servletContext());
+        }
+
+        return jakartaServletWebApplication;
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() throws Exception {
+
+                ThymeleafEndpoint endpoint = new ThymeleafEndpoint();
+                endpoint.setCamelContext(context);
+                endpoint.setJakartaServletWebApplication(jakartaServletWebApplication());
+                endpoint.setAllowContextMapAll(true);
+                endpoint.setResourceUri("letter");
+                endpoint.setPrefix("WEB-INF/templates/");
+                endpoint.setSuffix(".html");
+                endpoint.setResolver(ThymeleafResolverType.WEB_APP);
+                endpoint.setCacheable(true);
+                endpoint.setCacheTimeToLive(500L);
+                endpoint.setEncoding("UTF-8");
+                endpoint.setCheckExistence(true);
+                endpoint.setOrder(1);
+                endpoint.setTemplateMode("HTML");
+
+                context.addEndpoint(TEST_ENDPOINT, endpoint);
+
+                from(DIRECT_START)
+                        .setBody(simple(SPAZZ_TESTING_SERVICE))
+                        .to(TEST_ENDPOINT)
+                        .to(MOCK_RESULT);
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverTest.java
new file mode 100644
index 00000000000..e16270a2962
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverTest.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import java.io.File;
+import java.io.InputStream;
+
+import jakarta.servlet.ServletContext;
+
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.ITemplateResolver;
+import org.thymeleaf.templateresolver.WebApplicationTemplateResolver;
+import org.thymeleaf.web.servlet.JakartaServletWebApplication;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+
+public class ThymeleafWebApplicationResolverTest extends ThymeleafAbstractBaseTest {
+
+    private static final String TEST_ENDPOINT = "testEndpoint";
+
+    private ServletContext servletContext;
+
+    private JakartaServletWebApplication jakartaServletWebApplication;
+
+    @BeforeEach
+    public void setUp() throws Exception {
+
+        super.setUp();
+
+        File initialFile = new File("src/test/resources/WEB-INF/templates/letter.html");
+        InputStream targetStream = FileUtils.openInputStream(initialFile);
+        Mockito.when(servletContext.getResourceAsStream(anyString())).thenReturn(targetStream);
+    }
+
+    @Test
+    public void testThymeleaf() throws InterruptedException {
+
+        MockEndpoint mock = getMockEndpoint(MOCK_RESULT);
+        mock.expectedMessageCount(1);
+        mock.message(0).body().contains(THANK_YOU_FOR_YOUR_ORDER);
+        mock.message(0).body().endsWith(SPAZZ_TESTING_SERVICE);
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_TEMPLATE).isNull();
+        mock.message(0).header(ThymeleafConstants.THYMELEAF_VARIABLE_MAP).isNull();
+        mock.message(0).header(FIRST_NAME).isEqualTo(JANE);
+
+        template.request(DIRECT_START, basicHeaderProcessor);
+
+        mock.assertIsSatisfied();
+
+        ThymeleafEndpoint thymeleafEndpoint = context.getEndpoint(TEST_ENDPOINT, ThymeleafEndpoint.class);
+
+        assertAll("properties",
+                () -> assertNotNull(thymeleafEndpoint),
+                () -> assertTrue(thymeleafEndpoint.isAllowContextMapAll()),
+                () -> assertNull(thymeleafEndpoint.getCacheable()),
+                () -> assertNull(thymeleafEndpoint.getCacheTimeToLive()),
+                () -> assertNull(thymeleafEndpoint.getCheckExistence()),
+                () -> assertNull(thymeleafEndpoint.getEncoding()),
+                () -> assertEquals(ExchangePattern.InOut, thymeleafEndpoint.getExchangePattern()),
+                () -> assertNull(thymeleafEndpoint.getOrder()),
+                () -> assertNull(thymeleafEndpoint.getPrefix()),
+                () -> assertEquals(ThymeleafResolverType.WEB_APP, thymeleafEndpoint.getResolver()),
+                () -> assertNull(thymeleafEndpoint.getSuffix()),
+                () -> assertNotNull(thymeleafEndpoint.getTemplateEngine()),
+                () -> assertNull(thymeleafEndpoint.getTemplateMode()));
+
+        assertEquals(1, thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().size());
+        ITemplateResolver resolver = thymeleafEndpoint.getTemplateEngine().getTemplateResolvers().stream().findFirst().get();
+        assertTrue(resolver instanceof WebApplicationTemplateResolver);
+
+        WebApplicationTemplateResolver templateResolver = (WebApplicationTemplateResolver) resolver;
+        assertAll("templateResolver",
+                () -> assertTrue(templateResolver.isCacheable()),
+                () -> assertNull(templateResolver.getCacheTTLMs()),
+                () -> assertNull(templateResolver.getCharacterEncoding()),
+                () -> assertFalse(templateResolver.getCheckExistence()),
+                () -> assertNull(templateResolver.getOrder()),
+                () -> assertNull(templateResolver.getPrefix()),
+                () -> assertNull(templateResolver.getSuffix()),
+                () -> assertEquals(TemplateMode.HTML, templateResolver.getTemplateMode()));
+    }
+
+    private ServletContext servletContext() {
+
+        if (servletContext == null) {
+            servletContext = mock(ServletContext.class);
+        }
+
+        return servletContext;
+    }
+
+    private JakartaServletWebApplication jakartaServletWebApplication() {
+
+        if (jakartaServletWebApplication == null) {
+            jakartaServletWebApplication = JakartaServletWebApplication.buildApplication(servletContext());
+        }
+
+        return jakartaServletWebApplication;
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() throws Exception {
+
+                ThymeleafEndpoint endpoint = new ThymeleafEndpoint();
+                endpoint.setCamelContext(context);
+                endpoint.setJakartaServletWebApplication(jakartaServletWebApplication());
+                endpoint.setAllowContextMapAll(true);
+                endpoint.setResourceUri("WEB-INF/templates/letter.html");
+                endpoint.setResolver(ThymeleafResolverType.WEB_APP);
+
+                context.addEndpoint(TEST_ENDPOINT, endpoint);
+
+                from(DIRECT_START)
+                        .setBody(simple(SPAZZ_TESTING_SERVICE))
+                        .to(TEST_ENDPOINT)
+                        .to(MOCK_RESULT);
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/resources/WEB-INF/templates/letter.html b/components/camel-thymeleaf/src/test/resources/WEB-INF/templates/letter.html
index 0023e1d2877..98f74e223c6 100644
--- a/components/camel-thymeleaf/src/test/resources/WEB-INF/templates/letter.html
+++ b/components/camel-thymeleaf/src/test/resources/WEB-INF/templates/letter.html
@@ -16,9 +16,9 @@
     limitations under the License.
 
 -->
-Dear [[${headers.lastName}]], [[${headers.firstName}]]
+Dear <span th:remove="tag" th:text="${headers.lastName}"/>, <span th:remove="tag" th:text="${headers.firstName}"/>
 
-Thanks for the order of [[${headers.item}]].
+Thank you for your order number [(${exchange.properties.orderNumber})] of [(${headers.item})].
 
 Regards Camel Riders Bookstore
-[[${body}]]
\ No newline at end of file
+<span th:remove="tag" th:text="${body}"/>
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/log4j2.properties b/components/camel-thymeleaf/src/test/resources/log4j2.properties
index 88a74e81ca1..4aafcbf3eed 100644
--- a/components/camel-thymeleaf/src/test/resources/log4j2.properties
+++ b/components/camel-thymeleaf/src/test/resources/log4j2.properties
@@ -27,6 +27,10 @@ appender.stdout.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
 rootLogger.level = INFO
 rootLogger.appenderRef.out.ref = out
 rootLogger.appenderRef.stdout.ref = stdout
-logger.thymeleaf.name = org.apache.camel.component.thymeleaf
-logger.thymeleaf.level = DEBUG
+#logger.thymeleaf.name = org.apache.camel.component.thymeleaf
+#logger.thymeleaf.level = INFO
+logger.camel.name = org.apache.camel
+logger.camel.level = DEBUG
+logger.springframework.name = org.springframework
+logger.springframework.level = INFO
 
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/OrangeTemplate.txt b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/OrangeTemplate.txt
deleted file mode 100644
index 0a76babaf81..00000000000
--- a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/OrangeTemplate.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-<#--
-
-    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.
-
--->
-${request.setHeader('fruit', 'orange')}I am an ${body}
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/BodyAsDomainObject.txt b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/apple.html
similarity index 84%
rename from components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/BodyAsDomainObject.txt
rename to components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/apple.html
index 7648c82b5f2..15d2edab677 100644
--- a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/BodyAsDomainObject.txt
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/apple.html
@@ -1,20 +1,19 @@
-<#--
-
-    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.
-
--->
-Hi ${body.givenName} how are you? Its a nice day.
-Give my regards to the family ${body.familyName}.
\ No newline at end of file
+<!--
+
+    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.
+
+-->
+<span th:text="${request.setHeader('fruit', 'apple')}" th:remove="tag"/>I am an <span th:text="${body}" th:remove="tag"/>
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/camel-context.xml b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/camel-context.xml
index c1646cf5b70..990f2b67a6d 100644
--- a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/camel-context.xml
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/camel-context.xml
@@ -24,17 +24,17 @@
        http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
 
   <camelContext xmlns="http://camel.apache.org/schema/spring">
-    <route>
+    <route trace="true">
 	   	<from uri="direct:start"/>
 	    <filter>
 	   		<method ref="fruitFilter" method="isApple"/>
-        	<to uri="thymeleaf:org/apache/camel/component/thymeleaf/AppleTemplate.ftl?allowContextMapAll=true" />
+        	<to uri="thymeleaf:org/apache/camel/component/thymeleaf/apple.html?templateMode=HTML&amp;allowContextMapAll=true" />
         	<to uri="mock:result" />
 	    </filter>
 	    <filter>
 	   		<method ref="fruitFilter" method="isOrange"/>
-        	<to uri="thymeleaf:org/apache/camel/component/thymeleaf/OrangeTemplate.ftl?allowContextMapAll=true" />
-    	    <to uri="mock:result" />
+        	<to uri="thymeleaf:org/apache/camel/component/thymeleaf/orange.html?templateMode=HTML&amp;allowContextMapAll=true" />
+			<to uri="mock:result" />
 	    </filter>
    </route>
   </camelContext>
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/Concurrent.txt b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/concurrent.txt
similarity index 100%
rename from components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/Concurrent.txt
rename to components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/concurrent.txt
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/example.txt b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/example.txt
deleted file mode 100644
index b7e6e721a68..00000000000
--- a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/example.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-<#--
-
-    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.
-
--->
-Dear ${headers.name}. You ordered item ${exchange.properties.item} on ${body}.
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/header.txt b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/header.txt
deleted file mode 100644
index 666463f16b0..00000000000
--- a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/header.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-<#--
-
-    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.
-
--->
-Dear ${headers.lastName}, ${headers.firstName}
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letterWithoutHeader.txt b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter-domain.html
similarity index 76%
rename from components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letterWithoutHeader.txt
rename to components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter-domain.html
index 3c9f6ca851b..a682369f64a 100644
--- a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letterWithoutHeader.txt
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter-domain.html
@@ -1,4 +1,4 @@
-<#--
+<!--
 
     Licensed to the Apache Software Foundation (ASF) under one or more
     contributor license agreements.  See the NOTICE file distributed with
@@ -16,9 +16,9 @@
     limitations under the License.
 
 -->
-${body}
+Dear <span th:remove="tag" th:text="${body.lastName}"/>, <span th:remove="tag" th:text="${body.firstName}"/>
 
-Thanks for the order of ${headers.item}.
+Thank you for your order number [(${exchange.properties.orderNumber})] of [(${body.item})].
 
 Regards Camel Riders Bookstore
-PS: Next beer is on me, James
\ No newline at end of file
+<span th:remove="tag" th:text="${body.closing}"/>
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter-utf16.txt b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter-utf16.txt
deleted file mode 100644
index d435ae55e98..00000000000
Binary files a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter-utf16.txt and /dev/null differ
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.css b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.css
deleted file mode 100644
index 9d4c33de3f2..00000000000
--- a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.css
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * 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.
- */
-<!--/*
-    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.
-
-    Comments are not supported in CSS templates, so this ASF header will appear in the rendered text.
-*/-->
-# just a comment
-.fixed_header tbody {
-    display: /*[(${headers.display})]*/ inline;
-    overflow: auto;
-    height: /*[(${headers.height})]*/ 1.0em;
-}
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.html b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.html
index 0023e1d2877..98f74e223c6 100644
--- a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.html
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.html
@@ -16,9 +16,9 @@
     limitations under the License.
 
 -->
-Dear [[${headers.lastName}]], [[${headers.firstName}]]
+Dear <span th:remove="tag" th:text="${headers.lastName}"/>, <span th:remove="tag" th:text="${headers.firstName}"/>
 
-Thanks for the order of [[${headers.item}]].
+Thank you for your order number [(${exchange.properties.orderNumber})] of [(${headers.item})].
 
 Regards Camel Riders Bookstore
-[[${body}]]
\ No newline at end of file
+<span th:remove="tag" th:text="${body}"/>
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.js b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.js
deleted file mode 100644
index 90ca6984c27..00000000000
--- a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.js
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.
- */
-<!--/*
-    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.
-
-    Comments are not supported in JAVASCRIPT templates, so this ASF header will appear in the rendered text.
-*/-->
-<span th:fragment="show-hide-content" th:remove="tag">
-    <script th:inline="javascript">
-        function hideContent() {
-            showContentButton = document.getElementById(/*[[${headers.showContentButton}]]*/ 'showContentButton');
-            hideContentButton = document.getElementById(/*[[${headers.hideContentButton}]]*/ 'hideContentButton');
-            someContent = document.getElementById(/*[[${body}]]*/ 'someContent');
-
-            showContentButton.style.display = 'block';
-            hideContentButton.style.display = 'none';
-            someContent.style.display = 'none';
-        }
-
-        function showContent() {
-            showContentButton = document.getElementById(/*[[${headers.showContentButton}]]*/ 'showContentButton');
-            hideContentButton = document.getElementById(/*[[${headers.hideContentButton}]]*/ 'hideContentButton');
-            someContent = document.getElementById(/*[[${body}]]*/ 'someContent');
-
-            showContentButton.style.display = 'none';
-            hideContentButton.style.display = 'block';
-            someContent.style.display = 'block';
-        }
-    </script>
-</span>
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.txt b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.txt
index 2a2e9ae4b0f..51e11dbbacf 100644
--- a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.txt
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.txt
@@ -19,7 +19,7 @@
 <!--/* This code will be removed at thymeleaf parsing time! */-->
 Dear [(${headers.lastName})], [(${headers.firstName})]
 
-Thanks for the order of [(${headers.item})].
+Thank you for your order number [(${exchange.properties.orderNumber})] of [(${headers.item})].
 
 Regards Camel Riders Bookstore
 [(${body})]
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.xml b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.xml
deleted file mode 100644
index 3355c6c3a52..00000000000
--- a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?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.
-
--->
-<letter>
-    <greeting>
-        Dear [[${headers.lastName}]], [[${headers.firstName}]]
-    </greeting>
-    <message>
-        Thanks for the order of [[${headers.item}]].
-    </message>
-    <closing>
-        Regards Camel Riders Bookstore
-    </closing>
-    <signature th:attr="content=${body}">
-        1 Jupiter Road, Junit, CA 98765
-    </signature>
-</letter>
-
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letterWithUrl.html b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letterWithUrl.html
index 66801707d43..eee4b76fc27 100644
--- a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letterWithUrl.html
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letterWithUrl.html
@@ -16,9 +16,11 @@
     limitations under the License.
 
 -->
-Dear [[${headers.lastName}]], [[${headers.firstName}]]
+Dear <span th:remove="tag" th:text="${headers.lastName}"/>, <span th:remove="tag" th:text="${headers.firstName}"/>
+
+Thank you for your order number [(${exchange.properties.orderNumber})] of [(${headers.item})].
 
-Thanks for the order of [[${headers.item}]].
 <span th:replace="~{http://localhost:9843/dontcare.html :: test}"/>
+
 Regards Camel Riders Bookstore
-[[${body}]]
\ No newline at end of file
+<span th:remove="tag" th:text="${body}"/>
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/AppleTemplate.txt b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/orange.html
similarity index 84%
rename from components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/AppleTemplate.txt
rename to components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/orange.html
index c8d3ac0f493..c86e7acd22b 100644
--- a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/AppleTemplate.txt
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/orange.html
@@ -1,4 +1,4 @@
-<#--
+<!--
 
     Licensed to the Apache Software Foundation (ASF) under one or more
     contributor license agreements.  See the NOTICE file distributed with
@@ -16,4 +16,4 @@
     limitations under the License.
 
 -->
-${request.setHeader('fruit', 'apple')}I am an ${body}
\ No newline at end of file
+<span th:text="${request.setHeader('fruit', 'orange')}" th:remove="tag"/>I am an <span th:text="${body}" th:remove="tag"/>
\ No newline at end of file


[camel] 09/10: Fixing PR build errors

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 8afe42f713cfc91a6eafbe1d2b62f949a228beb2
Author: Craig Ziesman <cz...@redhat.com>
AuthorDate: Mon Sep 11 13:49:31 2023 -0500

    Fixing PR build errors
---
 .../resources/org/apache/camel/catalog/schemas/camel-spring.xsd         | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
index 6ef43282182..4572bd2431d 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
@@ -439,7 +439,7 @@ Enriches a message with data from a secondary resource
     <xs:annotation>
       <xs:documentation xml:lang="en">
 <![CDATA[
-Error handler settings
+Camel error handling.
 ]]>
       </xs:documentation>
     </xs:annotation>


[camel] 08/10: Added auto-generated new files and updated files due to new Thymeleaf component

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 117ccb9ad405483e807176534c724ba520ee0f53
Author: Craig Ziesman <cz...@redhat.com>
AuthorDate: Fri Sep 8 10:01:38 2023 -0500

    Added auto-generated new files and updated files due to new Thymeleaf component
---
 .../org/apache/camel/catalog/components.properties |   1 +
 .../apache/camel/catalog/components/thymeleaf.json |  49 ++
 .../apache/camel/catalog/schemas/camel-spring.xsd  |   2 +-
 .../org/apache/camel/main/components.properties    |   1 +
 .../modules/ROOT/examples/json/thymeleaf.json      |   1 +
 docs/components/modules/ROOT/nav.adoc              |   1 +
 .../modules/ROOT/pages/thymeleaf-component.adoc    |   1 +
 .../component/ComponentsBuilderFactory.java        |  13 +
 .../dsl/ThymeleafComponentBuilderFactory.java      | 121 +++++
 .../src/generated/resources/metadata.json          |  22 +
 .../builder/endpoint/EndpointBuilderFactory.java   |   1 +
 .../camel/builder/endpoint/EndpointBuilders.java   |   1 +
 .../builder/endpoint/StaticEndpointBuilders.java   |  55 +++
 .../dsl/ThymeleafEndpointBuilderFactory.java       | 536 +++++++++++++++++++++
 .../camel-component-known-dependencies.properties  |   1 +
 15 files changed, 805 insertions(+), 1 deletion(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
index b6e196d2221..d541e37e79c 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
@@ -295,6 +295,7 @@ string-template
 stub
 telegram
 thrift
+thymeleaf
 tika
 timer
 twilio
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/thymeleaf.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/thymeleaf.json
new file mode 100644
index 00000000000..07f99ce1ed7
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/thymeleaf.json
@@ -0,0 +1,49 @@
+{
+  "component": {
+    "kind": "component",
+    "name": "thymeleaf",
+    "title": "Thymeleaf",
+    "description": "Transform messages using a Thymeleaf template.",
+    "deprecated": false,
+    "firstVersion": "1.0.0",
+    "label": "transformation",
+    "javaType": "org.apache.camel.component.thymeleaf.ThymeleafComponent",
+    "supportLevel": "Stable",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-thymeleaf",
+    "version": "4.1.0-SNAPSHOT",
+    "scheme": "thymeleaf",
+    "extendsScheme": "",
+    "syntax": "thymeleaf:templatePath",
+    "async": false,
+    "api": false,
+    "consumerOnly": false,
+    "producerOnly": true,
+    "lenientProperties": false
+  },
+  "componentProperties": {
+    "lazyStartProducer": { "index": 0, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
+    "autowiredEnabled": { "index": 1, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...]
+  },
+  "headers": {
+    "CamelThymeleafResourceUri": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of the Thymeleaf template.", "constantName": "org.apache.camel.component.thymeleaf.ThymeleafConstants#THYMELEAF_RESOURCE_URI" },
+    "CamelThymeleafTemplate": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The content of the Thymeleaf template.", "constantName": "org.apache.camel.component.thymeleaf.ThymeleafConstants#THYMELEAF_TEMPLATE" },
+    "CamelThymeleafVariableMap": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Map<String, Object>", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The value of this header should be a Map with key\/values that will be override any existing key with the same name. This can be used to preconfigure common key\/values you want to reuse in your Thymeleaf endpoints.", "cons [...]
+    "CamelThymeleafServletContext": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "jakarta.servlet.ServletContext", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The ServletContext for a web application.", "constantName": "org.apache.camel.component.thymeleaf.ThymeleafConstants#THYMELEAF_SERVLET_CONTEXT" }
+  },
+  "properties": {
+    "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will look [...]
+    "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and C [...]
+    "cacheable": { "index": 2, "kind": "parameter", "displayName": "Cacheable", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "description": "Whether templates have to be considered cacheable or not." },
+    "cacheTimeToLive": { "index": 3, "kind": "parameter", "displayName": "Cache Time To Live", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "description": "The cache Time To Live for templates, expressed in milliseconds." },
+    "checkExistence": { "index": 4, "kind": "parameter", "displayName": "Check Existence", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "description": "Whether a template resources will be checked for existence before being returned." },
+    "contentCache": { "index": 5, "kind": "parameter", "displayName": "Content Cache", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether to use resource content cache or not" },
+    "encoding": { "index": 6, "kind": "parameter", "displayName": "Encoding", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The character encoding to be used for reading template resources." },
+    "order": { "index": 7, "kind": "parameter", "displayName": "Order", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "description": "The order in which this template will be resolved as part of the resolver chain." },
+    "prefix": { "index": 8, "kind": "parameter", "displayName": "Prefix", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "An optional prefix added to template names to convert them into resource names." },
+    "resolver": { "index": 9, "kind": "parameter", "displayName": "Resolver", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.thymeleaf.ThymeleafResolverType", "enum": [ "CLASS_LOADER", "DEFAULT", "FILE", "STRING", "URL", "WEB_APP" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "CLASS_LOADER", "description": "The type of resolver to be used by the template engine." },
+    "suffix": { "index": 10, "kind": "parameter", "displayName": "Suffix", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "An optional suffix added to template names to convert them into resource names." },
+    "templateMode": { "index": 11, "kind": "parameter", "displayName": "Template Mode", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The template mode to be applied to templates." },
+    "lazyStartProducer": { "index": 12, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
+  }
+}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
index 4572bd2431d..6ef43282182 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
@@ -439,7 +439,7 @@ Enriches a message with data from a secondary resource
     <xs:annotation>
       <xs:documentation xml:lang="en">
 <![CDATA[
-Camel error handling.
+Error handler settings
 ]]>
       </xs:documentation>
     </xs:annotation>
diff --git a/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties b/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties
index b6e196d2221..d541e37e79c 100644
--- a/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties
+++ b/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties
@@ -295,6 +295,7 @@ string-template
 stub
 telegram
 thrift
+thymeleaf
 tika
 timer
 twilio
diff --git a/docs/components/modules/ROOT/examples/json/thymeleaf.json b/docs/components/modules/ROOT/examples/json/thymeleaf.json
new file mode 120000
index 00000000000..bfb96cbe841
--- /dev/null
+++ b/docs/components/modules/ROOT/examples/json/thymeleaf.json
@@ -0,0 +1 @@
+../../../../../../components/camel-thymeleaf/src/generated/resources/org/apache/camel/component/thymeleaf/thymeleaf.json
\ No newline at end of file
diff --git a/docs/components/modules/ROOT/nav.adoc b/docs/components/modules/ROOT/nav.adoc
index b74c494422c..eb4b6b1bcb2 100644
--- a/docs/components/modules/ROOT/nav.adoc
+++ b/docs/components/modules/ROOT/nav.adoc
@@ -299,6 +299,7 @@
 ** xref:stub-component.adoc[Stub]
 ** xref:telegram-component.adoc[Telegram]
 ** xref:thrift-component.adoc[Thrift]
+** xref:thymeleaf-component.adoc[Thymeleaf]
 ** xref:tika-component.adoc[Tika]
 ** xref:timer-component.adoc[Timer]
 ** xref:twilio-component.adoc[Twilio]
diff --git a/docs/components/modules/ROOT/pages/thymeleaf-component.adoc b/docs/components/modules/ROOT/pages/thymeleaf-component.adoc
new file mode 120000
index 00000000000..1e2dda48415
--- /dev/null
+++ b/docs/components/modules/ROOT/pages/thymeleaf-component.adoc
@@ -0,0 +1 @@
+../../../../../components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc
\ No newline at end of file
diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
index f95592f16c9..96899f9b5bf 100644
--- a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
+++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
@@ -3985,6 +3985,19 @@ public interface ComponentsBuilderFactory {
     static org.apache.camel.builder.component.dsl.ThriftComponentBuilderFactory.ThriftComponentBuilder thrift() {
         return org.apache.camel.builder.component.dsl.ThriftComponentBuilderFactory.thrift();
     }
+    /**
+     * Thymeleaf (camel-thymeleaf)
+     * Transform messages using a Thymeleaf template.
+     * 
+     * Category: transformation
+     * Since: 1.0
+     * Maven coordinates: org.apache.camel:camel-thymeleaf
+     * 
+     * @return the dsl builder
+     */
+    static org.apache.camel.builder.component.dsl.ThymeleafComponentBuilderFactory.ThymeleafComponentBuilder thymeleaf() {
+        return org.apache.camel.builder.component.dsl.ThymeleafComponentBuilderFactory.thymeleaf();
+    }
     /**
      * Tika (camel-tika)
      * Parse documents and extract metadata and text using Apache Tika.
diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/ThymeleafComponentBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/ThymeleafComponentBuilderFactory.java
new file mode 100644
index 00000000000..ec1a8ec3780
--- /dev/null
+++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/ThymeleafComponentBuilderFactory.java
@@ -0,0 +1,121 @@
+/*
+ * 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.builder.component.dsl;
+
+import javax.annotation.processing.Generated;
+import org.apache.camel.Component;
+import org.apache.camel.builder.component.AbstractComponentBuilder;
+import org.apache.camel.builder.component.ComponentBuilder;
+import org.apache.camel.component.thymeleaf.ThymeleafComponent;
+
+/**
+ * Transform messages using a Thymeleaf template.
+ * 
+ * Generated by camel-package-maven-plugin - do not edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.ComponentDslMojo")
+public interface ThymeleafComponentBuilderFactory {
+
+    /**
+     * Thymeleaf (camel-thymeleaf)
+     * Transform messages using a Thymeleaf template.
+     * 
+     * Category: transformation
+     * Since: 1.0
+     * Maven coordinates: org.apache.camel:camel-thymeleaf
+     * 
+     * @return the dsl builder
+     */
+    static ThymeleafComponentBuilder thymeleaf() {
+        return new ThymeleafComponentBuilderImpl();
+    }
+
+    /**
+     * Builder for the Thymeleaf component.
+     */
+    interface ThymeleafComponentBuilder
+            extends
+                ComponentBuilder<ThymeleafComponent> {
+        /**
+         * Whether the producer should be started lazy (on the first message).
+         * By starting lazy you can use this to allow CamelContext and routes to
+         * startup in situations where a producer may otherwise fail during
+         * starting and cause the route to fail being started. By deferring this
+         * startup to be lazy then the startup failure can be handled during
+         * routing messages via Camel's routing error handlers. Beware that when
+         * the first message is processed then creating and starting the
+         * producer may take a little time and prolong the total processing time
+         * of the processing.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: producer
+         * 
+         * @param lazyStartProducer the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafComponentBuilder lazyStartProducer(
+                boolean lazyStartProducer) {
+            doSetProperty("lazyStartProducer", lazyStartProducer);
+            return this;
+        }
+        /**
+         * Whether autowiring is enabled. This is used for automatic autowiring
+         * options (the option must be marked as autowired) by looking up in the
+         * registry to find if there is a single instance of matching type,
+         * which then gets configured on the component. This can be used for
+         * automatic configuring JDBC data sources, JMS connection factories,
+         * AWS Clients, etc.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: true
+         * Group: advanced
+         * 
+         * @param autowiredEnabled the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafComponentBuilder autowiredEnabled(
+                boolean autowiredEnabled) {
+            doSetProperty("autowiredEnabled", autowiredEnabled);
+            return this;
+        }
+    }
+
+    class ThymeleafComponentBuilderImpl
+            extends
+                AbstractComponentBuilder<ThymeleafComponent>
+            implements
+                ThymeleafComponentBuilder {
+        @Override
+        protected ThymeleafComponent buildConcreteComponent() {
+            return new ThymeleafComponent();
+        }
+        @Override
+        protected boolean setPropertyOnComponent(
+                Component component,
+                String name,
+                Object value) {
+            switch (name) {
+            case "lazyStartProducer": ((ThymeleafComponent) component).setLazyStartProducer((boolean) value); return true;
+            case "autowiredEnabled": ((ThymeleafComponent) component).setAutowiredEnabled((boolean) value); return true;
+            default: return false;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/dsl/camel-componentdsl/src/generated/resources/metadata.json b/dsl/camel-componentdsl/src/generated/resources/metadata.json
index b2b34ae56b5..c74c2d9a7b9 100644
--- a/dsl/camel-componentdsl/src/generated/resources/metadata.json
+++ b/dsl/camel-componentdsl/src/generated/resources/metadata.json
@@ -6588,6 +6588,28 @@
     "producerOnly": false,
     "lenientProperties": false
   },
+  "ThymeleafComponentBuilderFactory": {
+    "kind": "component",
+    "name": "thymeleaf",
+    "title": "Thymeleaf",
+    "description": "Transform messages using a Thymeleaf template.",
+    "deprecated": false,
+    "firstVersion": "1.0.0",
+    "label": "transformation",
+    "javaType": "org.apache.camel.component.thymeleaf.ThymeleafComponent",
+    "supportLevel": "Stable",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-thymeleaf",
+    "version": "4.1.0-SNAPSHOT",
+    "scheme": "thymeleaf",
+    "extendsScheme": "",
+    "syntax": "thymeleaf:templatePath",
+    "async": false,
+    "api": false,
+    "consumerOnly": false,
+    "producerOnly": true,
+    "lenientProperties": false
+  },
   "TikaComponentBuilderFactory": {
     "kind": "component",
     "name": "tika",
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
index fd487c3abcd..9e0c2add79a 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
@@ -311,6 +311,7 @@ public interface EndpointBuilderFactory
             org.apache.camel.builder.endpoint.dsl.SwiftEndpointBuilderFactory.SwiftBuilders,
             org.apache.camel.builder.endpoint.dsl.TelegramEndpointBuilderFactory.TelegramBuilders,
             org.apache.camel.builder.endpoint.dsl.ThriftEndpointBuilderFactory.ThriftBuilders,
+            org.apache.camel.builder.endpoint.dsl.ThymeleafEndpointBuilderFactory.ThymeleafBuilders,
             org.apache.camel.builder.endpoint.dsl.TikaEndpointBuilderFactory.TikaBuilders,
             org.apache.camel.builder.endpoint.dsl.TimerEndpointBuilderFactory.TimerBuilders,
             org.apache.camel.builder.endpoint.dsl.Timestream2EndpointBuilderFactory.Timestream2Builders,
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java
index 593df8dcf6b..581ded9343e 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java
@@ -308,6 +308,7 @@ public interface EndpointBuilders
             org.apache.camel.builder.endpoint.dsl.SwiftEndpointBuilderFactory,
             org.apache.camel.builder.endpoint.dsl.TelegramEndpointBuilderFactory,
             org.apache.camel.builder.endpoint.dsl.ThriftEndpointBuilderFactory,
+            org.apache.camel.builder.endpoint.dsl.ThymeleafEndpointBuilderFactory,
             org.apache.camel.builder.endpoint.dsl.TikaEndpointBuilderFactory,
             org.apache.camel.builder.endpoint.dsl.TimerEndpointBuilderFactory,
             org.apache.camel.builder.endpoint.dsl.Timestream2EndpointBuilderFactory,
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
index b632170141e..1ff7eb91e5c 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
@@ -13904,6 +13904,61 @@ public class StaticEndpointBuilders {
             String path) {
         return org.apache.camel.builder.endpoint.dsl.ThriftEndpointBuilderFactory.endpointBuilder(componentName, path);
     }
+    /**
+     * Thymeleaf (camel-thymeleaf)
+     * Transform messages using a Thymeleaf template.
+     * 
+     * Category: transformation
+     * Since: 1.0
+     * Maven coordinates: org.apache.camel:camel-thymeleaf
+     * 
+     * Syntax: <code>thymeleaf:templatePath</code>
+     * 
+     * Path parameter: resourceUri (required)
+     * Path to the resource. You can prefix with: classpath, file, http, ref, or
+     * bean. classpath, file and http loads the resource using these protocols
+     * (classpath is default). ref will lookup the resource in the registry.
+     * bean will call a method on a bean to be used as the resource. For bean
+     * you can specify the method name after dot, eg bean:myBean.myMethod.
+     * This option can also be loaded from an existing file, by prefixing with
+     * file: or classpath: followed by the location of the file.
+     * 
+     * @param path templatePath
+     * @return the dsl builder
+     */
+    public static org.apache.camel.builder.endpoint.dsl.ThymeleafEndpointBuilderFactory.ThymeleafEndpointBuilder thymeleaf(
+            String path) {
+        return org.apache.camel.builder.endpoint.dsl.ThymeleafEndpointBuilderFactory.endpointBuilder("thymeleaf", path);
+    }
+    /**
+     * Thymeleaf (camel-thymeleaf)
+     * Transform messages using a Thymeleaf template.
+     * 
+     * Category: transformation
+     * Since: 1.0
+     * Maven coordinates: org.apache.camel:camel-thymeleaf
+     * 
+     * Syntax: <code>thymeleaf:templatePath</code>
+     * 
+     * Path parameter: resourceUri (required)
+     * Path to the resource. You can prefix with: classpath, file, http, ref, or
+     * bean. classpath, file and http loads the resource using these protocols
+     * (classpath is default). ref will lookup the resource in the registry.
+     * bean will call a method on a bean to be used as the resource. For bean
+     * you can specify the method name after dot, eg bean:myBean.myMethod.
+     * This option can also be loaded from an existing file, by prefixing with
+     * file: or classpath: followed by the location of the file.
+     * 
+     * @param componentName to use a custom component name for the endpoint
+     * instead of the default name
+     * @param path templatePath
+     * @return the dsl builder
+     */
+    public static org.apache.camel.builder.endpoint.dsl.ThymeleafEndpointBuilderFactory.ThymeleafEndpointBuilder thymeleaf(
+            String componentName,
+            String path) {
+        return org.apache.camel.builder.endpoint.dsl.ThymeleafEndpointBuilderFactory.endpointBuilder(componentName, path);
+    }
     /**
      * Tika (camel-tika)
      * Parse documents and extract metadata and text using Apache Tika.
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ThymeleafEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ThymeleafEndpointBuilderFactory.java
new file mode 100644
index 00000000000..d3a78df9d02
--- /dev/null
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ThymeleafEndpointBuilderFactory.java
@@ -0,0 +1,536 @@
+/*
+ * 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.builder.endpoint.dsl;
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.function.*;
+import java.util.stream.*;
+import javax.annotation.processing.Generated;
+import org.apache.camel.builder.EndpointConsumerBuilder;
+import org.apache.camel.builder.EndpointProducerBuilder;
+import org.apache.camel.builder.endpoint.AbstractEndpointBuilder;
+
+/**
+ * Transform messages using a Thymeleaf template.
+ * 
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.EndpointDslMojo")
+public interface ThymeleafEndpointBuilderFactory {
+
+
+    /**
+     * Builder for endpoint for the Thymeleaf component.
+     */
+    public interface ThymeleafEndpointBuilder extends EndpointProducerBuilder {
+        default AdvancedThymeleafEndpointBuilder advanced() {
+            return (AdvancedThymeleafEndpointBuilder) this;
+        }
+        /**
+         * Sets whether the context map should allow access to all details. By
+         * default only the message body and headers can be accessed. This
+         * option can be enabled for full access to the current Exchange and
+         * CamelContext. Doing so impose a potential security risk as this opens
+         * access to the full power of CamelContext API.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: producer
+         * 
+         * @param allowContextMapAll the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder allowContextMapAll(
+                boolean allowContextMapAll) {
+            doSetProperty("allowContextMapAll", allowContextMapAll);
+            return this;
+        }
+        /**
+         * Sets whether the context map should allow access to all details. By
+         * default only the message body and headers can be accessed. This
+         * option can be enabled for full access to the current Exchange and
+         * CamelContext. Doing so impose a potential security risk as this opens
+         * access to the full power of CamelContext API.
+         * 
+         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
+         * type.
+         * 
+         * Default: false
+         * Group: producer
+         * 
+         * @param allowContextMapAll the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder allowContextMapAll(
+                String allowContextMapAll) {
+            doSetProperty("allowContextMapAll", allowContextMapAll);
+            return this;
+        }
+        /**
+         * Whether templates have to be considered cacheable or not.
+         * 
+         * The option is a: &lt;code&gt;java.lang.Boolean&lt;/code&gt; type.
+         * 
+         * Group: producer
+         * 
+         * @param cacheable the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder cacheable(Boolean cacheable) {
+            doSetProperty("cacheable", cacheable);
+            return this;
+        }
+        /**
+         * Whether templates have to be considered cacheable or not.
+         * 
+         * The option will be converted to a
+         * &lt;code&gt;java.lang.Boolean&lt;/code&gt; type.
+         * 
+         * Group: producer
+         * 
+         * @param cacheable the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder cacheable(String cacheable) {
+            doSetProperty("cacheable", cacheable);
+            return this;
+        }
+        /**
+         * The cache Time To Live for templates, expressed in milliseconds.
+         * 
+         * The option is a: &lt;code&gt;java.lang.Long&lt;/code&gt; type.
+         * 
+         * Group: producer
+         * 
+         * @param cacheTimeToLive the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder cacheTimeToLive(Long cacheTimeToLive) {
+            doSetProperty("cacheTimeToLive", cacheTimeToLive);
+            return this;
+        }
+        /**
+         * The cache Time To Live for templates, expressed in milliseconds.
+         * 
+         * The option will be converted to a
+         * &lt;code&gt;java.lang.Long&lt;/code&gt; type.
+         * 
+         * Group: producer
+         * 
+         * @param cacheTimeToLive the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder cacheTimeToLive(String cacheTimeToLive) {
+            doSetProperty("cacheTimeToLive", cacheTimeToLive);
+            return this;
+        }
+        /**
+         * Whether a template resources will be checked for existence before
+         * being returned.
+         * 
+         * The option is a: &lt;code&gt;java.lang.Boolean&lt;/code&gt; type.
+         * 
+         * Group: producer
+         * 
+         * @param checkExistence the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder checkExistence(Boolean checkExistence) {
+            doSetProperty("checkExistence", checkExistence);
+            return this;
+        }
+        /**
+         * Whether a template resources will be checked for existence before
+         * being returned.
+         * 
+         * The option will be converted to a
+         * &lt;code&gt;java.lang.Boolean&lt;/code&gt; type.
+         * 
+         * Group: producer
+         * 
+         * @param checkExistence the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder checkExistence(String checkExistence) {
+            doSetProperty("checkExistence", checkExistence);
+            return this;
+        }
+        /**
+         * Sets whether to use resource content cache or not.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: producer
+         * 
+         * @param contentCache the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder contentCache(boolean contentCache) {
+            doSetProperty("contentCache", contentCache);
+            return this;
+        }
+        /**
+         * Sets whether to use resource content cache or not.
+         * 
+         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
+         * type.
+         * 
+         * Default: false
+         * Group: producer
+         * 
+         * @param contentCache the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder contentCache(String contentCache) {
+            doSetProperty("contentCache", contentCache);
+            return this;
+        }
+        /**
+         * The character encoding to be used for reading template resources.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Group: producer
+         * 
+         * @param encoding the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder encoding(String encoding) {
+            doSetProperty("encoding", encoding);
+            return this;
+        }
+        /**
+         * The order in which this template will be resolved as part of the
+         * resolver chain.
+         * 
+         * The option is a: &lt;code&gt;java.lang.Integer&lt;/code&gt; type.
+         * 
+         * Group: producer
+         * 
+         * @param order the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder order(Integer order) {
+            doSetProperty("order", order);
+            return this;
+        }
+        /**
+         * The order in which this template will be resolved as part of the
+         * resolver chain.
+         * 
+         * The option will be converted to a
+         * &lt;code&gt;java.lang.Integer&lt;/code&gt; type.
+         * 
+         * Group: producer
+         * 
+         * @param order the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder order(String order) {
+            doSetProperty("order", order);
+            return this;
+        }
+        /**
+         * An optional prefix added to template names to convert them into
+         * resource names.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Group: producer
+         * 
+         * @param prefix the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder prefix(String prefix) {
+            doSetProperty("prefix", prefix);
+            return this;
+        }
+        /**
+         * The type of resolver to be used by the template engine.
+         * 
+         * The option is a:
+         * &lt;code&gt;org.apache.camel.component.thymeleaf.ThymeleafResolverType&lt;/code&gt; type.
+         * 
+         * Default: CLASS_LOADER
+         * Group: producer
+         * 
+         * @param resolver the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder resolver(
+                org.apache.camel.component.thymeleaf.ThymeleafResolverType resolver) {
+            doSetProperty("resolver", resolver);
+            return this;
+        }
+        /**
+         * The type of resolver to be used by the template engine.
+         * 
+         * The option will be converted to a
+         * &lt;code&gt;org.apache.camel.component.thymeleaf.ThymeleafResolverType&lt;/code&gt; type.
+         * 
+         * Default: CLASS_LOADER
+         * Group: producer
+         * 
+         * @param resolver the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder resolver(String resolver) {
+            doSetProperty("resolver", resolver);
+            return this;
+        }
+        /**
+         * An optional suffix added to template names to convert them into
+         * resource names.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Group: producer
+         * 
+         * @param suffix the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder suffix(String suffix) {
+            doSetProperty("suffix", suffix);
+            return this;
+        }
+        /**
+         * The template mode to be applied to templates.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Group: producer
+         * 
+         * @param templateMode the value to set
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder templateMode(String templateMode) {
+            doSetProperty("templateMode", templateMode);
+            return this;
+        }
+    }
+
+    /**
+     * Advanced builder for endpoint for the Thymeleaf component.
+     */
+    public interface AdvancedThymeleafEndpointBuilder
+            extends
+                EndpointProducerBuilder {
+        default ThymeleafEndpointBuilder basic() {
+            return (ThymeleafEndpointBuilder) this;
+        }
+        /**
+         * Whether the producer should be started lazy (on the first message).
+         * By starting lazy you can use this to allow CamelContext and routes to
+         * startup in situations where a producer may otherwise fail during
+         * starting and cause the route to fail being started. By deferring this
+         * startup to be lazy then the startup failure can be handled during
+         * routing messages via Camel's routing error handlers. Beware that when
+         * the first message is processed then creating and starting the
+         * producer may take a little time and prolong the total processing time
+         * of the processing.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: producer (advanced)
+         * 
+         * @param lazyStartProducer the value to set
+         * @return the dsl builder
+         */
+        default AdvancedThymeleafEndpointBuilder lazyStartProducer(
+                boolean lazyStartProducer) {
+            doSetProperty("lazyStartProducer", lazyStartProducer);
+            return this;
+        }
+        /**
+         * Whether the producer should be started lazy (on the first message).
+         * By starting lazy you can use this to allow CamelContext and routes to
+         * startup in situations where a producer may otherwise fail during
+         * starting and cause the route to fail being started. By deferring this
+         * startup to be lazy then the startup failure can be handled during
+         * routing messages via Camel's routing error handlers. Beware that when
+         * the first message is processed then creating and starting the
+         * producer may take a little time and prolong the total processing time
+         * of the processing.
+         * 
+         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
+         * type.
+         * 
+         * Default: false
+         * Group: producer (advanced)
+         * 
+         * @param lazyStartProducer the value to set
+         * @return the dsl builder
+         */
+        default AdvancedThymeleafEndpointBuilder lazyStartProducer(
+                String lazyStartProducer) {
+            doSetProperty("lazyStartProducer", lazyStartProducer);
+            return this;
+        }
+    }
+
+    public interface ThymeleafBuilders {
+        /**
+         * Thymeleaf (camel-thymeleaf)
+         * Transform messages using a Thymeleaf template.
+         * 
+         * Category: transformation
+         * Since: 1.0
+         * Maven coordinates: org.apache.camel:camel-thymeleaf
+         * 
+         * @return the dsl builder for the headers' name.
+         */
+        default ThymeleafHeaderNameBuilder thymeleaf() {
+            return ThymeleafHeaderNameBuilder.INSTANCE;
+        }
+        /**
+         * Thymeleaf (camel-thymeleaf)
+         * Transform messages using a Thymeleaf template.
+         * 
+         * Category: transformation
+         * Since: 1.0
+         * Maven coordinates: org.apache.camel:camel-thymeleaf
+         * 
+         * Syntax: <code>thymeleaf:templatePath</code>
+         * 
+         * Path parameter: resourceUri (required)
+         * Path to the resource. You can prefix with: classpath, file, http,
+         * ref, or bean. classpath, file and http loads the resource using these
+         * protocols (classpath is default). ref will lookup the resource in the
+         * registry. bean will call a method on a bean to be used as the
+         * resource. For bean you can specify the method name after dot, eg
+         * bean:myBean.myMethod.
+         * This option can also be loaded from an existing file, by prefixing
+         * with file: or classpath: followed by the location of the file.
+         * 
+         * @param path templatePath
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder thymeleaf(String path) {
+            return ThymeleafEndpointBuilderFactory.endpointBuilder("thymeleaf", path);
+        }
+        /**
+         * Thymeleaf (camel-thymeleaf)
+         * Transform messages using a Thymeleaf template.
+         * 
+         * Category: transformation
+         * Since: 1.0
+         * Maven coordinates: org.apache.camel:camel-thymeleaf
+         * 
+         * Syntax: <code>thymeleaf:templatePath</code>
+         * 
+         * Path parameter: resourceUri (required)
+         * Path to the resource. You can prefix with: classpath, file, http,
+         * ref, or bean. classpath, file and http loads the resource using these
+         * protocols (classpath is default). ref will lookup the resource in the
+         * registry. bean will call a method on a bean to be used as the
+         * resource. For bean you can specify the method name after dot, eg
+         * bean:myBean.myMethod.
+         * This option can also be loaded from an existing file, by prefixing
+         * with file: or classpath: followed by the location of the file.
+         * 
+         * @param componentName to use a custom component name for the endpoint
+         * instead of the default name
+         * @param path templatePath
+         * @return the dsl builder
+         */
+        default ThymeleafEndpointBuilder thymeleaf(
+                String componentName,
+                String path) {
+            return ThymeleafEndpointBuilderFactory.endpointBuilder(componentName, path);
+        }
+    }
+
+    /**
+     * The builder of headers' name for the Thymeleaf component.
+     */
+    public static class ThymeleafHeaderNameBuilder {
+        /**
+         * The internal instance of the builder used to access to all the
+         * methods representing the name of headers.
+         */
+        private static final ThymeleafHeaderNameBuilder INSTANCE = new ThymeleafHeaderNameBuilder();
+
+        /**
+         * The name of the Thymeleaf template.
+         * 
+         * The option is a: {@code String} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code ThymeleafResourceUri}.
+         */
+        public String thymeleafResourceUri() {
+            return "ThymeleafResourceUri";
+        }
+
+        /**
+         * The content of the Thymeleaf template.
+         * 
+         * The option is a: {@code String} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code ThymeleafTemplate}.
+         */
+        public String thymeleafTemplate() {
+            return "ThymeleafTemplate";
+        }
+
+        /**
+         * The value of this header should be a Map with key/values that will be
+         * override any existing key with the same name. This can be used to
+         * preconfigure common key/values you want to reuse in your Thymeleaf
+         * endpoints.
+         * 
+         * The option is a: {@code Map<String, Object>} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code ThymeleafVariableMap}.
+         */
+        public String thymeleafVariableMap() {
+            return "ThymeleafVariableMap";
+        }
+
+        /**
+         * The ServletContext for a web application.
+         * 
+         * The option is a: {@code jakarta.servlet.ServletContext} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code ThymeleafServletContext}.
+         */
+        public String thymeleafServletContext() {
+            return "ThymeleafServletContext";
+        }
+    }
+    static ThymeleafEndpointBuilder endpointBuilder(
+            String componentName,
+            String path) {
+        class ThymeleafEndpointBuilderImpl extends AbstractEndpointBuilder implements ThymeleafEndpointBuilder, AdvancedThymeleafEndpointBuilder {
+            public ThymeleafEndpointBuilderImpl(String path) {
+                super(componentName, path);
+            }
+        }
+        return new ThymeleafEndpointBuilderImpl(path);
+    }
+}
\ No newline at end of file
diff --git a/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties b/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties
index 51543551966..27631e6d681 100644
--- a/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties
+++ b/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties
@@ -300,6 +300,7 @@ org.apache.camel.component.stringtemplate.StringTemplateComponent=camel:stringte
 org.apache.camel.component.stub.StubComponent=camel:stub
 org.apache.camel.component.telegram.TelegramComponent=camel:telegram
 org.apache.camel.component.thrift.ThriftComponent=camel:thrift
+org.apache.camel.component.thymeleaf.ThymeleafComponent=camel:thymeleaf
 org.apache.camel.component.tika.TikaComponent=camel:tika
 org.apache.camel.component.timer.TimerComponent=camel:timer
 org.apache.camel.component.twilio.TwilioComponent=camel:twilio


[camel] 01/10: Initial commit of camel-thymeleaf

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit ee7c4a5611882c5ea669c1adf50ba72931009ec8
Author: Craig Ziesman <cz...@redhat.com>
AuthorDate: Mon Aug 28 13:15:25 2023 -0500

    Initial commit of camel-thymeleaf
---
 components/camel-thymeleaf/pom.xml                 |  95 ++++
 .../thymeleaf/ThymeleafComponentConfigurer.java    |  73 +++
 .../thymeleaf/ThymeleafEndpointConfigurer.java     |  82 +++
 .../thymeleaf/ThymeleafEndpointUriFactory.java     |  75 +++
 .../services/org/apache/camel/component.properties |   7 +
 .../services/org/apache/camel/component/thymeleaf  |   2 +
 .../apache/camel/configurer/thymeleaf-component    |   2 +
 .../org/apache/camel/configurer/thymeleaf-endpoint |   2 +
 .../org/apache/camel/urifactory/thymeleaf-endpoint |   2 +
 .../camel/component/thymeleaf/thymeleaf.json       |  48 ++
 .../src/main/docs/thymeleaf-component.adoc         | 255 +++++++++
 .../component/thymeleaf/ThymeleafComponent.java    |  96 ++++
 .../component/thymeleaf/ThymeleafConstants.java    |  47 ++
 .../component/thymeleaf/ThymeleafEndpoint.java     | 572 +++++++++++++++++++++
 .../component/thymeleaf/ThymeleafResolverType.java |  27 +
 .../component/thymeleaf/BruteForceCssTest.java     | 235 +++++++++
 .../thymeleaf/BruteForceJavascriptTest.java        | 258 ++++++++++
 .../camel/component/thymeleaf/BruteForceTest.java  | 317 ++++++++++++
 .../thymeleaf/BruteForceWebAppResolverTest.java    | 127 +++++
 .../thymeleaf/BruteForceWiremockTest.java          | 107 ++++
 .../camel/component/thymeleaf/FruitFilter.java     |  31 ++
 .../thymeleaf/ThymeleafAttachmentsTest.java        |  76 +++
 .../thymeleaf/ThymeleafBodyAsDomainObjectTest.java |  98 ++++
 .../thymeleaf/ThymeleafConcurrentTest.java         |  79 +++
 .../thymeleaf/ThymeleafContentCacheTest.java       | 193 +++++++
 .../component/thymeleaf/ThymeleafEncodingTest.java |  36 ++
 .../component/thymeleaf/ThymeleafEndpointTest.java |  46 ++
 .../thymeleaf/ThymeleafFileLetterTest.java         |  37 ++
 .../component/thymeleaf/ThymeleafLetterTest.java   |  73 +++
 .../ThymeleafLetterWithoutHeaderTest.java          |  36 ++
 .../thymeleaf/ThymeleafOverrideHeaderTest.java     |  97 ++++
 .../thymeleaf/ThymeleafSetHeaderTest.java          |  64 +++
 .../thymeleaf/ThymeleafTemplateInHeaderTest.java   | 100 ++++
 .../camel/component/thymeleaf/ThymeleafTest.java   |  92 ++++
 .../thymeleaf/ThymeleafValuesInPropertiesTest.java |  70 +++
 .../test/resources/WEB-INF/templates/letter.html   |  24 +
 .../src/test/resources/log4j2.properties           |  32 ++
 .../camel/component/thymeleaf/AppleTemplate.txt    |  19 +
 .../component/thymeleaf/BodyAsDomainObject.txt     |  20 +
 .../camel/component/thymeleaf/Concurrent.txt       |  19 +
 .../camel/component/thymeleaf/OrangeTemplate.txt   |  19 +
 .../camel/component/thymeleaf/camel-context.xml    |  44 ++
 .../apache/camel/component/thymeleaf/example.txt   |  19 +
 .../apache/camel/component/thymeleaf/header.txt    |  19 +
 .../camel/component/thymeleaf/letter-utf16.txt     | Bin 0 -> 2166 bytes
 .../apache/camel/component/thymeleaf/letter.css    |  40 ++
 .../apache/camel/component/thymeleaf/letter.html   |  24 +
 .../org/apache/camel/component/thymeleaf/letter.js |  57 ++
 .../apache/camel/component/thymeleaf/letter.txt    |  25 +
 .../apache/camel/component/thymeleaf/letter.xml    |  34 ++
 .../camel/component/thymeleaf/letterWithUrl.html   |  24 +
 .../component/thymeleaf/letterWithoutHeader.txt    |  24 +
 52 files changed, 4000 insertions(+)

diff --git a/components/camel-thymeleaf/pom.xml b/components/camel-thymeleaf/pom.xml
new file mode 100644
index 00000000000..3d2f1d9eca9
--- /dev/null
+++ b/components/camel-thymeleaf/pom.xml
@@ -0,0 +1,95 @@
+<?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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>components</artifactId>
+        <version>4.1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-thymeleaf</artifactId>
+    <packaging>jar</packaging>
+    <name>Camel :: Thymeleaf</name>
+    <description>Camel Thymeleaf support</description>
+
+    <properties>
+        <thymeleaf-version>3.1.2.RELEASE</thymeleaf-version>
+        <jakarta-servlet-api-version>6.0.0</jakarta-servlet-api-version>
+        <wiremock-version>3.0.0-beta-15</wiremock-version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-support</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.thymeleaf</groupId>
+            <artifactId>thymeleaf</artifactId>
+            <version>${thymeleaf-version}</version>
+        </dependency>
+
+        <!-- test dependencies -->
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-spring-junit5</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-attachments</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-management</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-slf4j2-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.wiremock</groupId>
+            <artifactId>wiremock</artifactId>
+            <version>${wiremock-version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>jakarta.servlet</groupId>
+            <artifactId>jakarta.servlet-api</artifactId>
+            <version>${jakarta-servlet-api-version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafComponentConfigurer.java b/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafComponentConfigurer.java
new file mode 100644
index 00000000000..09f9259f230
--- /dev/null
+++ b/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafComponentConfigurer.java
@@ -0,0 +1,73 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.thymeleaf;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.support.component.PropertyConfigurerSupport;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@SuppressWarnings("unchecked")
+public class ThymeleafComponentConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
+        ThymeleafComponent target = (ThymeleafComponent) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowcontextmapall":
+        case "allowContextMapAll": target.setAllowContextMapAll(property(camelContext, boolean.class, value)); return true;
+        case "allowtemplatefromheader":
+        case "allowTemplateFromHeader": target.setAllowTemplateFromHeader(property(camelContext, boolean.class, value)); return true;
+        case "autowiredenabled":
+        case "autowiredEnabled": target.setAutowiredEnabled(property(camelContext, boolean.class, value)); return true;
+        case "lazystartproducer":
+        case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
+        case "templateengine":
+        case "templateEngine": target.setTemplateEngine(property(camelContext, org.thymeleaf.TemplateEngine.class, value)); return true;
+        default: return false;
+        }
+    }
+
+    @Override
+    public Class<?> getOptionType(String name, boolean ignoreCase) {
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowcontextmapall":
+        case "allowContextMapAll": return boolean.class;
+        case "allowtemplatefromheader":
+        case "allowTemplateFromHeader": return boolean.class;
+        case "autowiredenabled":
+        case "autowiredEnabled": return boolean.class;
+        case "lazystartproducer":
+        case "lazyStartProducer": return boolean.class;
+        case "templateengine":
+        case "templateEngine": return org.thymeleaf.TemplateEngine.class;
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+        ThymeleafComponent target = (ThymeleafComponent) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowcontextmapall":
+        case "allowContextMapAll": return target.isAllowContextMapAll();
+        case "allowtemplatefromheader":
+        case "allowTemplateFromHeader": return target.isAllowTemplateFromHeader();
+        case "autowiredenabled":
+        case "autowiredEnabled": return target.isAutowiredEnabled();
+        case "lazystartproducer":
+        case "lazyStartProducer": return target.isLazyStartProducer();
+        case "templateengine":
+        case "templateEngine": return target.getTemplateEngine();
+        default: return null;
+        }
+    }
+}
+
diff --git a/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointConfigurer.java b/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointConfigurer.java
new file mode 100644
index 00000000000..8aee40302f9
--- /dev/null
+++ b/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointConfigurer.java
@@ -0,0 +1,82 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.thymeleaf;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.support.component.PropertyConfigurerSupport;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@SuppressWarnings("unchecked")
+public class ThymeleafEndpointConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
+        ThymeleafEndpoint target = (ThymeleafEndpoint) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowcontextmapall":
+        case "allowContextMapAll": target.setAllowContextMapAll(property(camelContext, boolean.class, value)); return true;
+        case "allowtemplatefromheader":
+        case "allowTemplateFromHeader": target.setAllowTemplateFromHeader(property(camelContext, boolean.class, value)); return true;
+        case "contentcache":
+        case "contentCache": target.setContentCache(property(camelContext, boolean.class, value)); return true;
+        case "encoding": target.setEncoding(property(camelContext, java.lang.String.class, value)); return true;
+        case "lazystartproducer":
+        case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
+        case "loadercache":
+        case "loaderCache": target.setLoaderCache(property(camelContext, boolean.class, value)); return true;
+        case "propertiesfile":
+        case "propertiesFile": target.setPropertiesFile(property(camelContext, java.lang.String.class, value)); return true;
+        default: return false;
+        }
+    }
+
+    @Override
+    public Class<?> getOptionType(String name, boolean ignoreCase) {
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowcontextmapall":
+        case "allowContextMapAll": return boolean.class;
+        case "allowtemplatefromheader":
+        case "allowTemplateFromHeader": return boolean.class;
+        case "contentcache":
+        case "contentCache": return boolean.class;
+        case "encoding": return java.lang.String.class;
+        case "lazystartproducer":
+        case "lazyStartProducer": return boolean.class;
+        case "loadercache":
+        case "loaderCache": return boolean.class;
+        case "propertiesfile":
+        case "propertiesFile": return java.lang.String.class;
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+        ThymeleafEndpoint target = (ThymeleafEndpoint) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowcontextmapall":
+        case "allowContextMapAll": return target.isAllowContextMapAll();
+        case "allowtemplatefromheader":
+        case "allowTemplateFromHeader": return target.isAllowTemplateFromHeader();
+        case "contentcache":
+        case "contentCache": return target.isContentCache();
+        case "encoding": return target.getEncoding();
+        case "lazystartproducer":
+        case "lazyStartProducer": return target.isLazyStartProducer();
+        case "loadercache":
+        case "loaderCache": return target.isLoaderCache();
+        case "propertiesfile":
+        case "propertiesFile": return target.getPropertiesFile();
+        default: return null;
+        }
+    }
+}
+
diff --git a/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointUriFactory.java b/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointUriFactory.java
new file mode 100644
index 00000000000..8d767397c70
--- /dev/null
+++ b/components/camel-thymeleaf/src/generated/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointUriFactory.java
@@ -0,0 +1,75 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.thymeleaf;
+
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.spi.EndpointUriFactory;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+public class ThymeleafEndpointUriFactory extends org.apache.camel.support.component.EndpointUriFactorySupport implements EndpointUriFactory {
+
+    private static final String BASE = ":resourceUri";
+
+    private static final Set<String> PROPERTY_NAMES;
+    private static final Set<String> SECRET_PROPERTY_NAMES;
+    private static final Set<String> MULTI_VALUE_PREFIXES;
+    static {
+        Set<String> props = new HashSet<>(8);
+        props.add("allowContextMapAll");
+        props.add("allowTemplateFromHeader");
+        props.add("contentCache");
+        props.add("encoding");
+        props.add("lazyStartProducer");
+        props.add("loaderCache");
+        props.add("propertiesFile");
+        props.add("resourceUri");
+        PROPERTY_NAMES = Collections.unmodifiableSet(props);
+        SECRET_PROPERTY_NAMES = Collections.emptySet();
+        MULTI_VALUE_PREFIXES = Collections.emptySet();
+    }
+
+    @Override
+    public boolean isEnabled(String scheme) {
+        return "thymeleaf".equals(scheme);
+    }
+
+    @Override
+    public String buildUri(String scheme, Map<String, Object> properties, boolean encode) throws URISyntaxException {
+        String syntax = scheme + BASE;
+        String uri = syntax;
+
+        Map<String, Object> copy = new HashMap<>(properties);
+
+        uri = buildPathParameter(syntax, uri, "resourceUri", null, true, copy);
+        uri = buildQueryParameters(uri, copy, encode);
+        return uri;
+    }
+
+    @Override
+    public Set<String> propertyNames() {
+        return PROPERTY_NAMES;
+    }
+
+    @Override
+    public Set<String> secretPropertyNames() {
+        return SECRET_PROPERTY_NAMES;
+    }
+
+    @Override
+    public Set<String> multiValuePrefixes() {
+        return MULTI_VALUE_PREFIXES;
+    }
+
+    @Override
+    public boolean isLenientProperties() {
+        return false;
+    }
+}
+
diff --git a/components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/component.properties b/components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/component.properties
new file mode 100644
index 00000000000..4429c6a0412
--- /dev/null
+++ b/components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/component.properties
@@ -0,0 +1,7 @@
+# Generated by camel build tools - do NOT edit this file!
+components=thymeleaf
+groupId=org.apache.camel
+artifactId=camel-thymeleaf
+version=4.0.0-SNAPSHOT
+projectName=Camel :: thymeleaf
+projectDescription=Camel Thymeleaf support
diff --git a/components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/component/thymeleaf b/components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/component/thymeleaf
new file mode 100644
index 00000000000..dc11aa50802
--- /dev/null
+++ b/components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/component/thymeleaf
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.thymeleaf.ThymeleafComponent
diff --git a/components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/configurer/thymeleaf-component b/components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/configurer/thymeleaf-component
new file mode 100644
index 00000000000..a557eb2133d
--- /dev/null
+++ b/components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/configurer/thymeleaf-component
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.thymeleaf.ThymeleafComponentConfigurer
diff --git a/components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/configurer/thymeleaf-endpoint b/components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/configurer/thymeleaf-endpoint
new file mode 100644
index 00000000000..ac16374d690
--- /dev/null
+++ b/components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/configurer/thymeleaf-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.thymeleaf.ThymeleafEndpointConfigurer
diff --git a/components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/urifactory/thymeleaf-endpoint b/components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/urifactory/thymeleaf-endpoint
new file mode 100644
index 00000000000..60469f9521b
--- /dev/null
+++ b/components/camel-thymeleaf/src/generated/resources/META-INF/services/org/apache/camel/urifactory/thymeleaf-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.thymeleaf.ThymeleafEndpointUriFactory
diff --git a/components/camel-thymeleaf/src/generated/resources/org/apache/camel/component/thymeleaf/thymeleaf.json b/components/camel-thymeleaf/src/generated/resources/org/apache/camel/component/thymeleaf/thymeleaf.json
new file mode 100644
index 00000000000..4fb1119fe95
--- /dev/null
+++ b/components/camel-thymeleaf/src/generated/resources/org/apache/camel/component/thymeleaf/thymeleaf.json
@@ -0,0 +1,48 @@
+{
+  "component": {
+    "kind": "component",
+    "name": "thymeleaf",
+    "title": "Thymeleaf",
+    "description": "Transform messages using a Thymeleaf template.",
+    "deprecated": false,
+    "firstVersion": "1.0.0",
+    "label": "transformation",
+    "javaType": "org.apache.camel.component.thymeleaf.ThymeleafComponent",
+    "supportLevel": "Stable",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-thymeleaf",
+    "version": "4.0.0-SNAPSHOT",
+    "scheme": "thymeleaf",
+    "extendsScheme": "",
+    "syntax": "thymeleaf:resourceUri",
+    "async": false,
+    "api": false,
+    "consumerOnly": false,
+    "producerOnly": true,
+    "lenientProperties": false
+  },
+  "componentProperties": {
+    "allowContextMapAll": { "index": 0, "kind": "property", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and Ca [...]
+    "allowTemplateFromHeader": { "index": 1, "kind": "property", "displayName": "Allow Template From Header", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to allow to use resource template from header or not (default false). Enabling this allows to specify dynamic templates via message header. However this can be seen as a potential se [...]
+    "lazyStartProducer": { "index": 2, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
+    "autowiredEnabled": { "index": 3, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...]
+    "templateEngine": { "index": 4, "kind": "property", "displayName": "Template Engine", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.thymeleaf.TemplateEngine", "deprecated": false, "autowired": false, "secret": false, "description": "To use the TemplateEngine otherwise a new engine is created" }
+  },
+  "headers": {
+    "CamelThymeleafResourceUri": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of the Thymeleaf template.", "constantName": "org.apache.camel.component.thymeleaf.ThymeleafConstants#THYMELEAF_RESOURCE_URI" },
+    "CamelThymeleafTemplate": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The content of the Thymeleaf template.", "constantName": "org.apache.camel.component.thymeleaf.ThymeleafConstants#THYMELEAF_TEMPLATE" },
+    "CamelThymeleafContext": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "org.thymeleaf.context.Context", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Thymeleaf context to use.", "constantName": "org.apache.camel.component.thymeleaf.ThymeleafConstants#THYMELEAF_CONTEXT" },
+    "CamelThymeleafLocale": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "java.util.Locale", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The locale of the Thymeleaf context.", "constantName": "org.apache.camel.component.thymeleaf.ThymeleafConstants#THYMELEAF_LOCALE" },
+    "CamelThymeleafVariableMap": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Map<String, Object>", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "To add additional information to the used ThymeleafContext. The value of this header should be a Map with key\/values that will added (override any existing key with the same name). This can be used to pre setup some common [...]
+  },
+  "properties": {
+    "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will look [...]
+    "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and C [...]
+    "allowTemplateFromHeader": { "index": 2, "kind": "parameter", "displayName": "Allow Template From Header", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to allow to use resource template from header or not (default false). Enabling this allows to specify dynamic templates via message header. However this can be seen as a potential s [...]
+    "contentCache": { "index": 3, "kind": "parameter", "displayName": "Content Cache", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether to use resource content cache or not" },
+    "encoding": { "index": 4, "kind": "parameter", "displayName": "Encoding", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Character encoding of the resource content." },
+    "loaderCache": { "index": 5, "kind": "parameter", "displayName": "Loader Cache", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Enables \/ disables the thymeleaf resource loader cache which is enabled by default" },
+    "propertiesFile": { "index": 6, "kind": "parameter", "displayName": "Properties File", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The URI of the properties file which is used for TemplateEngine initialization." },
+    "lazyStartProducer": { "index": 7, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produc [...]
+  }
+}
diff --git a/components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc b/components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc
new file mode 100644
index 00000000000..a35288f720a
--- /dev/null
+++ b/components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc
@@ -0,0 +1,255 @@
+= Thymeleaf Component
+:doctitle: Thymeleaf
+:shortname: thymeleaf
+:artifactid: camel-thymeleaf
+:description: Transform messages using a Thymeleaf template.
+:since: 1.0
+:supportlevel: Stable
+:tabs-sync-option:
+:component-header: Only producer is supported
+//Manually maintained attributes
+:camel-spring-boot-name: thymeleaf
+
+*Since Camel {since}*
+
+*{component-header}*
+
+The Thymeleaf component allows you to process a message using a
+https://www.thymeleaf.org/[Thymeleaf] template. This can be very powerful
+when using Templating to generate responses for requests.
+
+Maven users will need to add the following dependency to their `pom.xml`
+for this component:
+
+[source,xml]
+------------------------------------------------------------
+<dependency>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>camel-thymeleaf</artifactId>
+    <version>x.x.x</version>
+    <!-- use the same version as your Camel core version -->
+</dependency>
+------------------------------------------------------------
+
+== URI format
+
+-------------------------------
+thymeleaf:templateName[?options]
+-------------------------------
+
+Where *templateName* is the classpath-local URI of the template to
+invoke; or the complete URL of the remote template (eg:
+\file://folder/myfile.txt).
+
+
+
+
+// component-configure options: START
+
+// component-configure options: END
+
+// component options: START
+include::partial$component-configure-options.adoc[]
+include::partial$component-endpoint-options.adoc[]
+// component options: END
+
+// endpoint options: START
+
+// endpoint options: END
+
+// component headers: START
+include::partial$component-endpoint-headers.adoc[]
+// component headers: END
+
+Headers set during the Thymeleaf evaluation are returned to the message
+and added as headers, thus making it possible to return values from
+Thymeleaf to the Message.
+
+For example, to set the header value of `fruit` in the Thymeleaf template
+`fruit-template.txt`:
+
+-------------------------------
+$in.setHeader("fruit", "Apple")
+-------------------------------
+
+The `fruit` header is now accessible from the `message.out.headers`.
+
+== Thymeleaf Context
+
+Camel will provide exchange information in the Thymeleaf context (just a
+`Map`). The `Exchange` is transfered as:
+
+[width="100%",cols="10%,90%",options="header",]
+|=======================================================================
+|key |value
+
+|`exchange` |The `Exchange` itself.
+
+|`exchange.properties` |The `Exchange` properties.
+
+|`headers` |The headers of the In message.
+
+|`camelContext` |The Camel Context instance.
+
+|`request` |The In message.
+
+|`in` |The In message.
+
+|`body` |The In message body.
+
+|`out` |The Out message (only for InOut message exchange pattern).
+
+|`response` |The Out message (only for InOut message exchange pattern).
+|=======================================================================
+
+You can set up a custom Thymeleaf Context yourself by
+setting property *allowTemplateFromHeader=true* and setting the message header *CamelThymeleafContext* like this
+
+[source,java]
+-----------------------------------------------------------------------
+EngineContext engineContext = new EngineContext(variableMap);
+exchange.getIn().setHeader("CamelThymeleafContext", engineContext);
+-----------------------------------------------------------------------
+
+== Hot reloading
+
+The Thymeleaf template resource is, by default, hot reloadable for both
+file and classpath resources (expanded jar). If you set
+`contentCache=true`, Camel will only load the resource once, and thus
+hot reloading is not possible. This scenario can be used in production,
+when the resource never changes.
+
+== Dynamic templates
+
+Camel provides two headers by which you can define a different resource
+location for a template or the template content itself. If any of these
+headers is set then Camel uses this over the endpoint configured
+resource. This allows you to provide a dynamic template at runtime.
+
+[width="100%",cols="10%,10%,80%",options="header",]
+|=======================================================================
+|Header |Type |Description
+
+|CamelThymeleafResourceUri |String |A URI for the template resource to use instead of the
+endpoint configured.
+
+|CamelThymeleafTemplate |String |The template to use instead of the endpoint configured.
+|=======================================================================
+
+== Samples
+
+For a simple use case, you could use something like:
+
+[source,java]
+----------------------------------------
+from("activemq:My.Queue").
+  to("thymeleaf:com/acme/MyResponse.txt");
+----------------------------------------
+
+To use a Thymeleaf template to formulate a response to a message for
+InOut message exchanges (where there is a `JMSReplyTo` header).
+
+If you want to use InOnly and consume the message and send it to another
+destination, you could use the following route:
+
+[source,java]
+----------------------------------------
+from("activemq:My.Queue")
+  .to("thymeleaf:com/acme/MyResponse.txt")
+  .to("activemq:Another.Queue");
+----------------------------------------
+
+And to use the content cache, e.g. for use in production, where the
+`.txt` template never changes:
+
+[source,java]
+----------------------------------------------------------
+from("activemq:My.Queue")
+  .to("thymeleaf:com/acme/MyResponse.txt?contentCache=true")
+  .to("activemq:Another.Queue");
+----------------------------------------------------------
+
+And a file based resource:
+
+[source,java]
+-----------------------------------------------------------------
+from("activemq:My.Queue")
+  .to("thymeleaf:file://myfolder/MyResponse.txt?contentCache=true")
+  .to("activemq:Another.Queue");
+-----------------------------------------------------------------
+
+It's possible to specify what template the component
+should use dynamically via a header, so for example:
+
+[source,java]
+---------------------------------------------------------------------------
+from("direct:in")
+  .setHeader("CamelThymeleafResourceUri").constant("path/to/my/template.txt")
+  .to("thymeleaf:dummy?allowTemplateFromHeader=true"");
+---------------------------------------------------------------------------
+
+It's possible to specify a template directly as a header
+the component should use dynamically via a header, so for example:
+
+[source,java]
+---------------------------------------------------------------------------------------------------------------
+from("direct:in")
+  .setHeader("CamelThymeleafTemplate").constant("Hi this is a thymeleaf template that can do templating ${body}")
+  .to("thymeleaf:dummy?allowTemplateFromHeader=true"");
+---------------------------------------------------------------------------------------------------------------
+
+== The Email Sample
+
+In this sample we want to use Thymeleaf templating for an order
+confirmation email. The email template is laid out in Thymeleaf as:
+
+.letter.txt
+[source,text]
+----------------------------------------------
+Dear ${headers.lastName}, ${headers.firstName}
+
+Thanks for the order of ${headers.item}.
+
+Regards Camel Riders Bookstore
+${body}
+----------------------------------------------
+
+And the java code (from an unit test):
+
+[source,java]
+----
+    private Exchange createLetter() {
+        Exchange exchange = context.getEndpoint("direct:a").createExchange();
+        Message msg = exchange.getIn();
+        msg.setHeader("firstName", "Claus");
+        msg.setHeader("lastName", "Ibsen");
+        msg.setHeader("item", "Camel in Action");
+        msg.setBody("PS: Next beer is on me, James");
+        return exchange;
+    }
+
+    @Test
+    public void testThymeleafLetter() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        mock.message(0).body(String.class).contains("Thanks for the order of Camel in Action");
+
+        template.send("direct:a", createLetter());
+
+        mock.assertIsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct:a")
+                    .to("thymeleaf:org/apache/camel/component/thymeleaf/letter.txt")
+                    .to("mock:result");
+            }
+        };
+    }
+----
+
+
+include::spring-boot:partial$starter.adoc[]
diff --git a/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafComponent.java b/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafComponent.java
new file mode 100644
index 00000000000..20be6854ecc
--- /dev/null
+++ b/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafComponent.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import java.util.Map;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.annotations.Component;
+import org.apache.camel.support.DefaultComponent;
+import org.thymeleaf.TemplateEngine;
+
+@Component("thymeleaf")
+public class ThymeleafComponent extends DefaultComponent {
+
+    //    @Metadata(defaultValue = "false")
+    //    private boolean allowTemplateFromHeader;
+
+    @Metadata(defaultValue = "false")
+    private boolean allowContextMapAll;
+
+    @Metadata(label = "advanced")
+    private TemplateEngine templateEngine;
+
+    public ThymeleafComponent() {
+
+    }
+
+    public TemplateEngine getTemplateEngine() {
+
+        return templateEngine;
+    }
+
+    /**
+     * To use the {@link TemplateEngine} otherwise a new engine is created
+     */
+    public void setTemplateEngine(TemplateEngine templateEngine) {
+
+        this.templateEngine = templateEngine;
+    }
+
+    //    public boolean isAllowTemplateFromHeader() {
+    //
+    //        return allowTemplateFromHeader;
+    //    }
+
+    /**
+     * Whether to allow to use resource template from header or not (default false).
+     * <p>
+     * Enabling this allows to specify dynamic templates via message header. However, this can be seen as a potential
+     * security vulnerability if the header is coming from a malicious user, so use this with care.
+     */
+    //    public void setAllowTemplateFromHeader(boolean allowTemplateFromHeader) {
+    //
+    //        this.allowTemplateFromHeader = allowTemplateFromHeader;
+    //    }
+
+    public boolean isAllowContextMapAll() {
+
+        return allowContextMapAll;
+    }
+
+    /**
+     * Sets whether the context map should allow access to all details. By default, only the message body and headers
+     * can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so
+     * impose a potential security risk as this opens access to the full power of CamelContext API.
+     */
+    public void setAllowContextMapAll(boolean allowContextMapAll) {
+
+        this.allowContextMapAll = allowContextMapAll;
+    }
+
+    @Override
+    protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
+
+        ThymeleafEndpoint endpoint = new ThymeleafEndpoint(uri, this, remaining);
+        setProperties(endpoint, parameters);
+
+        return endpoint;
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafConstants.java b/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafConstants.java
new file mode 100644
index 00000000000..4da163357f9
--- /dev/null
+++ b/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafConstants.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import org.apache.camel.spi.Metadata;
+
+public class ThymeleafConstants {
+
+    @Metadata(description = "The name of the Thymeleaf template.", javaType = "String")
+    public static final String THYMELEAF_RESOURCE_URI = "CamelThymeleafResourceUri";
+
+    @Metadata(description = "The content of the Thymeleaf template.", javaType = "String")
+    public static final String THYMELEAF_TEMPLATE = "CamelThymeleafTemplate";
+
+    @Metadata(description = "The Thymeleaf context to use.", javaType = "org.thymeleaf.context.Context")
+    public static final String THYMELEAF_CONTEXT = "CamelThymeleafContext";
+
+    @Metadata(description = "The locale of the Thymeleaf context.", javaType = "java.util.Locale")
+    public static final String THYMELEAF_LOCALE = "CamelThymeleafLocale";
+
+    @Metadata(description = "To add additional information to the used ThymeleafContext.\n" +
+                            "The value of this header should be a `Map` with key/values that will be\n" +
+                            "added and override any existing key with the same name. \n" +
+                            "This can be used to preconfigure common key/values you want to reuse\n" +
+                            "in your Thymeleaf endpoints.",
+              javaType = "Map<String, Object>")
+    public static final String THYMELEAF_VARIABLE_MAP = "CamelThymeleafVariableMap";
+
+    private ThymeleafConstants() {
+
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafEndpoint.java b/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafEndpoint.java
new file mode 100644
index 00000000000..e2ce9eced17
--- /dev/null
+++ b/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafEndpoint.java
@@ -0,0 +1,572 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import java.util.Map;
+
+import org.apache.camel.Category;
+import org.apache.camel.Component;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.ResourceEndpoint;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.support.ExchangeHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.thymeleaf.TemplateEngine;
+import org.thymeleaf.context.Context;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
+import org.thymeleaf.templateresolver.DefaultTemplateResolver;
+import org.thymeleaf.templateresolver.FileTemplateResolver;
+import org.thymeleaf.templateresolver.ITemplateResolver;
+import org.thymeleaf.templateresolver.StringTemplateResolver;
+import org.thymeleaf.templateresolver.UrlTemplateResolver;
+import org.thymeleaf.templateresolver.WebApplicationTemplateResolver;
+
+/**
+ * Transform messages using a Thymeleaf template.
+ */
+@UriEndpoint(firstVersion = "1.0.0", scheme = "thymeleaf", title = "Thymeleaf", syntax = "thymeleaf:resourceUri",
+             producerOnly = true, category = { Category.TRANSFORMATION }, headersClass = ThymeleafConstants.class)
+public class ThymeleafEndpoint extends ResourceEndpoint {
+
+    private TemplateEngine templateEngine;
+
+    @UriParam(defaultValue = "CLASS_LOADER", description = "The type of resolver to be used by the template engine.",
+              javaType = "org.apache.camel.component.thymeleaf.ThymeleafResolverType")
+    private ThymeleafResolverType resolver = ThymeleafResolverType.CLASS_LOADER;
+
+    @UriParam
+    private String templateMode;
+
+    @UriParam
+    private String prefix;
+
+    @UriParam
+    private String suffix;
+
+    @UriParam
+    private String template;
+
+    @UriParam
+    private String encoding;
+
+    @UriParam
+    private Integer order;
+
+    @UriParam
+    private Boolean checkExistence;
+
+    @UriParam
+    private Long cacheTimeToLive;
+
+    @UriParam
+    private Boolean cacheable;
+
+    public ThymeleafEndpoint() {
+
+    }
+
+    public ThymeleafEndpoint(String endpointURI, Component component, String resourceURI) {
+
+        super(endpointURI, component, resourceURI);
+    }
+
+    @Override
+    public ExchangePattern getExchangePattern() {
+
+        return ExchangePattern.InOut;
+    }
+
+    @Override
+    protected String createEndpointUri() {
+
+        return "thymeleaf:" + getResourceUri();
+    }
+
+    public String getTemplate() {
+
+        return template;
+    }
+
+    public void setTemplate(String template) {
+
+        this.template = template;
+    }
+
+    public String getTemplateMode() {
+
+        TemplateMode f;
+        return templateMode;
+    }
+
+    /**
+     * <p>
+     * Sets the template mode to be applied to templates resolved by this endpoint.
+     * </p>
+     * <p>
+     * One of {@code HTML}, {@code XML}, {@code TEXT}, {@code JAVASCRIPT}, {@code CSS}, {@code RAW}.
+     * </p>
+     * <p>
+     * Note that this template mode will be ignored if the template resource name ends in a known file name suffix:
+     * {@code .html}, {@code .htm}, {@code .xhtml}, {@code .xml}, {@code .js}, {@code .json}, {@code .css},
+     * {@code .rss}, {@code .atom}, {@code .txt}.
+     * </p>
+     *
+     * @param templateMode the template mode.
+     */
+    public void setTemplateMode(String templateMode) {
+
+        this.templateMode = templateMode;
+    }
+
+    public ThymeleafResolverType getResolver() {
+
+        return resolver;
+    }
+
+    /**
+     * Sets the type of resolver to be used by the template engine.
+     * <p>
+     * One of {@code CLASS_LOADER}, {@code DEFAULT}, {@code FILE}, {@code STRING}, {@code URL}, {@code WEB_APP}.
+     * </p>
+     */
+    public void setResolver(ThymeleafResolverType resolver) {
+
+        this.resolver = resolver;
+    }
+
+    public String getPrefix() {
+
+        return prefix;
+    }
+
+    /**
+     * <p>
+     * Sets a new (optional) prefix to be added to all template names in order to convert <i>template names</i> into
+     * <i>resource names</i>.
+     * </p>
+     *
+     * @param prefix the prefix to be set.
+     */
+    public void setPrefix(String prefix) {
+
+        this.prefix = prefix;
+    }
+
+    public String getSuffix() {
+
+        return suffix;
+    }
+
+    /**
+     * <p>
+     * Sets a new (optional) suffix to be added to all template names in order to convert <i>template names</i> into
+     * <i>resource names</i>.
+     * </p>
+     * <p>
+     * Note that this suffix may not be applied to the template name if the template name already ends in a known file
+     * name suffix: {@code .html}, {@code .htm}, {@code .xhtml}, {@code .xml}, {@code .js}, {@code .json}, {@code .css},
+     * {@code .rss}, {@code .atom}, {@code .txt}.
+     * </p>
+     *
+     * @param suffix the suffix to be set.
+     */
+    public void setSuffix(String suffix) {
+
+        this.suffix = suffix;
+    }
+
+    public String getEncoding() {
+
+        return encoding;
+    }
+
+    /**
+     * <p>
+     * Sets a new character encoding for reading template resources.
+     * </p>
+     *
+     * @param encoding the character encoding to be used.
+     */
+    public void setEncoding(String encoding) {
+
+        this.encoding = encoding;
+    }
+
+    public Integer getOrder() {
+
+        return order;
+    }
+
+    /**
+     * <p>
+     * Sets a new order for the template engine in the chain. Order should start with 1.
+     * </p>
+     *
+     * @param order the new order.
+     */
+    public void setOrder(Integer order) {
+
+        this.order = order;
+    }
+
+    public Boolean isCheckExistence() {
+
+        return checkExistence;
+    }
+
+    /**
+     * <p>
+     * Sets whether template resources will be checked for existence before being returned or not.
+     * </p>
+     * <p>
+     * Default value is {@code FALSE}.
+     * </p>
+     *
+     * @param checkExistence {@code true} if resource existence should be checked, {@code false} if not
+     */
+    public void setCheckExistence(Boolean checkExistence) {
+
+        this.checkExistence = checkExistence;
+    }
+
+    public Long getCacheTimeToLive() {
+
+        return cacheTimeToLive;
+    }
+
+    /**
+     * <p>
+     * Sets a new value for the cache TTL for resolved templates.
+     * </p>
+     * <p>
+     * If a template is resolved as <i>cacheable</i> but cache TTL is null, this means the template will live in cache
+     * until evicted by LRU (Least Recently Used) algorithm for being the oldest entry in cache.
+     * </p>
+     *
+     * @param cacheTimeToLive the new cache TTL in milliseconds, or null for using natural LRU eviction.
+     */
+    public void setCacheTimeToLive(Long cacheTimeToLive) {
+
+        this.cacheTimeToLive = cacheTimeToLive;
+    }
+
+    public Boolean isCacheable() {
+
+        return cacheable;
+    }
+
+    /**
+     * <p>
+     * Sets a new value for the <i>cacheable</i> flag.
+     * </p>
+     *
+     * @param cacheable whether resolved patterns should be considered cacheable or not.
+     */
+    public void setCacheable(Boolean cacheable) {
+
+        this.cacheable = cacheable;
+    }
+
+    private synchronized TemplateEngine getTemplateEngine() {
+
+        if (templateEngine == null) {
+            ITemplateResolver templateResolver;
+
+            switch (resolver) {
+                case CLASS_LOADER -> {
+                    templateResolver = classLoaderTemplateResolver();
+                }
+
+                case DEFAULT -> {
+                    templateResolver = defaultTemplateResolver();
+                }
+
+                case FILE -> {
+                    templateResolver = fileTemplateResolver();
+                }
+
+                case STRING -> {
+                    templateResolver = stringTemplateResolver();
+                }
+
+                case URL -> {
+                    templateResolver = urlTemplateResolver();
+                }
+
+                case WEB_APP -> {
+                    templateResolver = webApplicationTemplateResolver();
+                }
+
+                default -> {
+                    throw new RuntimeCamelException("cannot determine TemplateResolver for type " + resolver);
+                }
+            }
+
+            templateEngine = new TemplateEngine();
+            templateEngine.setTemplateResolver(templateResolver);
+        }
+
+        return templateEngine;
+    }
+
+    /**
+     * To use the {@link TemplateEngine} otherwise a new engine is created
+     */
+    public void setTemplateEngine(TemplateEngine templateEngine) {
+
+        this.templateEngine = templateEngine;
+    }
+
+    public ThymeleafEndpoint findOrCreateEndpoint(String uri, String newResourceUri) {
+
+        String newUri = uri.replace(getResourceUri(), newResourceUri);
+        log.debug("Getting endpoint with URI: {}", newUri);
+        return getCamelContext().getEndpoint(newUri, ThymeleafEndpoint.class);
+    }
+
+    @Override
+    protected void onExchange(Exchange exchange) throws Exception {
+
+        String path = getResourceUri();
+        ObjectHelper.notNull(path, "resourceUri");
+
+        String newResourceUri = exchange.getIn().getHeader(ThymeleafConstants.THYMELEAF_RESOURCE_URI, String.class);
+        if (newResourceUri != null) {
+            // remove the header to avoid it being propagated in the routing
+            exchange.getIn().removeHeader(ThymeleafConstants.THYMELEAF_RESOURCE_URI);
+
+            log.debug("{} set to {} creating new endpoint to handle exchange",
+                    ThymeleafConstants.THYMELEAF_RESOURCE_URI, newResourceUri);
+            ThymeleafEndpoint newEndpoint = findOrCreateEndpoint(getEndpointUri(), newResourceUri);
+            newEndpoint.onExchange(exchange);
+
+            return;
+        }
+
+        String template = exchange.getIn().getHeader(ThymeleafConstants.THYMELEAF_TEMPLATE, String.class);
+        if (template != null) {
+            // remove the header to avoid it being propagated in the routing
+            exchange.getIn().removeHeader(ThymeleafConstants.THYMELEAF_TEMPLATE);
+        }
+
+        Map<String, Object> dataModel = exchange.getIn().getHeader(ThymeleafConstants.THYMELEAF_VARIABLE_MAP, Map.class);
+        if (dataModel == null) {
+            dataModel = ExchangeHelper.createVariableMap(exchange, isAllowContextMapAll());
+        } else {
+            // remove the header to avoid it being propagated in the routing
+            exchange.getIn().removeHeader(ThymeleafConstants.THYMELEAF_VARIABLE_MAP);
+        }
+
+        // let thymeleaf parse and generate the result
+        TemplateEngine templateEngine = getTemplateEngine();
+
+        Context context = new Context();
+        context.setVariables(dataModel);
+
+        String buffer = templateEngine.process(template, context);
+
+        // now store the result in the exchange body
+        ExchangeHelper.setInOutBodyPatternAware(exchange, buffer);
+    }
+
+    private ITemplateResolver classLoaderTemplateResolver() {
+
+        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
+        if (cacheable != null) {
+            resolver.setCacheable(cacheable);
+        }
+        if (cacheTimeToLive != null) {
+            resolver.setCacheTTLMs(cacheTimeToLive);
+        }
+        if (encoding != null) {
+            resolver.setCharacterEncoding(encoding);
+        }
+        if (checkExistence != null) {
+            resolver.setCheckExistence(checkExistence);
+        }
+        if (order != null) {
+            resolver.setOrder(order);
+        }
+        if (prefix != null) {
+            resolver.setPrefix(prefix);
+        }
+        if (suffix != null) {
+            resolver.setSuffix(suffix);
+        }
+        if (templateMode != null) {
+            resolver.setTemplateMode(templateMode);
+        }
+        if (template == null) {
+            throw new RuntimeCamelException("template must be provided");
+        }
+
+        return resolver;
+    }
+
+    private ITemplateResolver defaultTemplateResolver() {
+
+        DefaultTemplateResolver resolver = new DefaultTemplateResolver();
+        if (checkExistence != null) {
+            resolver.setCheckExistence(checkExistence);
+        }
+        if (order != null) {
+            resolver.setOrder(order);
+        }
+        if (templateMode != null) {
+            resolver.setTemplateMode(templateMode);
+        }
+        if (template == null) {
+            throw new RuntimeCamelException("template must be provided");
+        } else {
+            resolver.setTemplate(template);
+        }
+
+        return resolver;
+    }
+
+    private ITemplateResolver fileTemplateResolver() {
+
+        FileTemplateResolver resolver = new FileTemplateResolver();
+        if (cacheable != null) {
+            resolver.setCacheable(cacheable);
+        }
+        if (cacheTimeToLive != null) {
+            resolver.setCacheTTLMs(cacheTimeToLive);
+        }
+        if (encoding != null) {
+            resolver.setCharacterEncoding(encoding);
+        }
+        if (checkExistence != null) {
+            resolver.setCheckExistence(checkExistence);
+        }
+        if (order != null) {
+            resolver.setOrder(order);
+        }
+        if (prefix != null) {
+            resolver.setPrefix(prefix);
+        }
+        if (suffix != null) {
+            resolver.setSuffix(suffix);
+        }
+        if (templateMode != null) {
+            resolver.setTemplateMode(templateMode);
+        }
+        if (template == null) {
+            throw new RuntimeCamelException("template must be provided");
+        }
+
+        return resolver;
+    }
+
+    private ITemplateResolver stringTemplateResolver() {
+
+        StringTemplateResolver resolver = new StringTemplateResolver();
+        if (cacheable != null) {
+            resolver.setCacheable(cacheable);
+        }
+        if (cacheTimeToLive != null) {
+            resolver.setCacheTTLMs(cacheTimeToLive);
+        }
+        if (checkExistence != null) {
+            resolver.setCheckExistence(checkExistence);
+        }
+        if (order != null) {
+            resolver.setOrder(order);
+        }
+        if (templateMode != null) {
+            resolver.setTemplateMode(templateMode);
+        }
+        if (template == null) {
+            throw new RuntimeCamelException("template must be provided");
+        }
+
+        return resolver;
+    }
+
+    private ITemplateResolver urlTemplateResolver() {
+
+        UrlTemplateResolver resolver = new UrlTemplateResolver();
+        if (cacheable != null) {
+            resolver.setCacheable(cacheable);
+        }
+        if (cacheTimeToLive != null) {
+            resolver.setCacheTTLMs(cacheTimeToLive);
+        }
+        if (encoding != null) {
+            resolver.setCharacterEncoding(encoding);
+        }
+        if (checkExistence != null) {
+            resolver.setCheckExistence(checkExistence);
+        }
+        if (order != null) {
+            resolver.setOrder(order);
+        }
+        if (prefix != null) {
+            resolver.setPrefix(prefix);
+        }
+        if (suffix != null) {
+            resolver.setSuffix(suffix);
+        }
+        if (templateMode != null) {
+            resolver.setTemplateMode(templateMode);
+        }
+        if (template == null) {
+            throw new RuntimeCamelException("template must be provided");
+        }
+
+        return resolver;
+    }
+
+    private ITemplateResolver webApplicationTemplateResolver() {
+
+        WebApplicationTemplateResolver resolver = new WebApplicationTemplateResolver(null);
+        if (cacheable != null) {
+            resolver.setCacheable(cacheable);
+        }
+        if (cacheTimeToLive != null) {
+            resolver.setCacheTTLMs(cacheTimeToLive);
+        }
+        if (encoding != null) {
+            resolver.setCharacterEncoding(encoding);
+        }
+        if (checkExistence != null) {
+            resolver.setCheckExistence(checkExistence);
+        }
+        if (order != null) {
+            resolver.setOrder(order);
+        }
+        if (prefix != null) {
+            resolver.setPrefix(prefix);
+        }
+        if (suffix != null) {
+            resolver.setSuffix(suffix);
+        }
+        if (templateMode != null) {
+            resolver.setTemplateMode(templateMode);
+        }
+        if (template == null) {
+            throw new RuntimeCamelException("template must be provided");
+        }
+
+        return resolver;
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafResolverType.java b/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafResolverType.java
new file mode 100644
index 00000000000..c24e45e58a0
--- /dev/null
+++ b/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafResolverType.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+public enum ThymeleafResolverType {
+
+    CLASS_LOADER,
+    DEFAULT,
+    FILE,
+    STRING,
+    URL,
+    WEB_APP
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceCssTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceCssTest.java
new file mode 100644
index 00000000000..b3ea17f9135
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceCssTest.java
@@ -0,0 +1,235 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.thymeleaf.TemplateEngine;
+import org.thymeleaf.context.Context;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
+import org.thymeleaf.templateresolver.DefaultTemplateResolver;
+import org.thymeleaf.templateresolver.StringTemplateResolver;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class BruteForceCssTest {
+
+    private static final String TEMPLATE_NAME = "letter";
+
+    private static final Logger LOG = LoggerFactory.getLogger(BruteForceCssTest.class);
+
+    @Test
+    public void testClassLoaderTemplateResolverCss() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.CSS);
+        resolver.setCharacterEncoding("UTF-8");
+        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
+        resolver.setSuffix(".css");
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testClassLoaderTemplateResolverTxt() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.TEXT);
+        resolver.setCharacterEncoding("UTF-8");
+        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
+        resolver.setSuffix(".css");
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testClassLoaderTemplateResolverHtml() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.HTML);
+        resolver.setCharacterEncoding("UTF-8");
+        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
+        resolver.setSuffix(".css");
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testDefaultTemplateResolverCss() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        DefaultTemplateResolver resolver = new DefaultTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.CSS);
+        resolver.setTemplate(cssTemplate());
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testDefaultTemplateResolverTxt() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        DefaultTemplateResolver resolver = new DefaultTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.TEXT);
+        resolver.setTemplate(cssTemplate());
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testDefaultTemplateResolverHtml() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        DefaultTemplateResolver resolver = new DefaultTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.HTML);
+        resolver.setTemplate(cssTemplate());
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testStringTemplateResolverCss() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        StringTemplateResolver resolver = new StringTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.CSS);
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(cssTemplate(), context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testStringTemplateResolverTxt() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        StringTemplateResolver resolver = new StringTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.TEXT);
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(cssTemplate(), context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testStringTemplateResolverHtml() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        StringTemplateResolver resolver = new StringTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.HTML);
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(cssTemplate(), context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    protected Context context() {
+
+        Context context = new Context();
+        context.setVariable("headers", headers());
+
+        return context;
+    }
+
+    protected Map<String, Object> headers() {
+
+        Map<String, Object> headers = new HashMap<>();
+        headers.put("display", "block");
+        headers.put("height", "5.6em");
+
+        return headers;
+    }
+
+    protected String cssTemplate() {
+
+        return """
+                <!--/*
+                    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.
+
+                    Comments are not supported in CSS templates, so this ASF header will appear in the rendered text.
+                */-->
+                # just a comment
+                .fixed_header tbody {
+                    display: /*[(${headers.display})]*/ inline;
+                    overflow: auto;
+                    height: /*[(${headers.height})]*/ 1.0em;
+                }
+                """;
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceJavascriptTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceJavascriptTest.java
new file mode 100644
index 00000000000..47ceec2a8f0
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceJavascriptTest.java
@@ -0,0 +1,258 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.thymeleaf.TemplateEngine;
+import org.thymeleaf.context.Context;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
+import org.thymeleaf.templateresolver.DefaultTemplateResolver;
+import org.thymeleaf.templateresolver.StringTemplateResolver;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class BruteForceJavascriptTest {
+
+    private static final String TEMPLATE_NAME = "letter";
+
+    private static final Logger LOG = LoggerFactory.getLogger(BruteForceJavascriptTest.class);
+
+    @Test
+    public void testClassLoaderTemplateResolverJavascript() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.JAVASCRIPT);
+        resolver.setCharacterEncoding("UTF-8");
+        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
+        resolver.setSuffix(".js");
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testClassLoaderTemplateResolverTxt() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.TEXT);
+        resolver.setCharacterEncoding("UTF-8");
+        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
+        resolver.setSuffix(".js");
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testClassLoaderTemplateResolverHtml() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.HTML);
+        resolver.setCharacterEncoding("UTF-8");
+        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
+        resolver.setSuffix(".js");
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testDefaultTemplateResolverJavascript() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        DefaultTemplateResolver resolver = new DefaultTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.JAVASCRIPT);
+        resolver.setTemplate(jsTemplate());
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testDefaultTemplateResolverTxt() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        DefaultTemplateResolver resolver = new DefaultTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.TEXT);
+        resolver.setTemplate(jsTemplate());
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testDefaultTemplateResolverHtml() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        DefaultTemplateResolver resolver = new DefaultTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.HTML);
+        resolver.setTemplate(jsTemplate());
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testStringTemplateResolverJavascript() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        StringTemplateResolver resolver = new StringTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.JAVASCRIPT);
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(jsTemplate(), context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testStringTemplateResolverTxt() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        StringTemplateResolver resolver = new StringTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.TEXT);
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(jsTemplate(), context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testStringTemplateResolverHtml() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        StringTemplateResolver resolver = new StringTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.HTML);
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(jsTemplate(), context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    protected Context context() {
+
+        Context context = new Context();
+        context.setVariable("headers", headers());
+        context.setVariable("body", body());
+
+        return context;
+    }
+
+    protected Map<String, Object> headers() {
+
+        Map<String, Object> headers = new HashMap<>();
+        headers.put("showContentButton", "testShowContentButton");
+        headers.put("hideContentButton", "testHideContentButton");
+
+        return headers;
+    }
+
+    protected Object body() {
+
+        return "testSomeContent";
+    }
+
+    protected String jsTemplate() {
+
+        return """
+                <!--/*
+                    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.
+
+                    Comments are not supported in JAVASCRIPT templates, so this ASF header will appear in the rendered text.
+                */-->
+                <span th:fragment="show-hide-content" th:remove="tag">
+                    <script th:inline="javascript">
+                        function hideContent() {
+                            showContentButton = document.getElementById(/*[[${headers.showContentButton}]]*/ 'showContentButton');
+                            hideContentButton = document.getElementById(/*[[${headers.hideContentButton}]]*/ 'hideContentButton');
+                            someContent = document.getElementById(/*[[${body}]]*/ 'someContent');
+
+                            showContentButton.style.display = 'block';
+                            hideContentButton.style.display = 'none';
+                            someContent.style.display = 'none';
+                        }
+
+                        function showContent() {
+                            showContentButton = document.getElementById(/*[[${headers.showContentButton}]]*/ 'showContentButton');
+                            hideContentButton = document.getElementById(/*[[${headers.hideContentButton}]]*/ 'hideContentButton');
+                            someContent = document.getElementById(/*[[${body}]]*/ 'someContent');
+
+                            showContentButton.style.display = 'none';
+                            hideContentButton.style.display = 'block';
+                            someContent.style.display = 'block';
+                        }
+                    </script>
+                </span>
+                """;
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceTest.java
new file mode 100644
index 00000000000..192677671bf
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceTest.java
@@ -0,0 +1,317 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.thymeleaf.TemplateEngine;
+import org.thymeleaf.context.Context;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
+import org.thymeleaf.templateresolver.DefaultTemplateResolver;
+import org.thymeleaf.templateresolver.FileTemplateResolver;
+import org.thymeleaf.templateresolver.StringTemplateResolver;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class BruteForceTest {
+
+    private static final String TEMPLATE_NAME = "letter";
+
+    private static final Logger LOG = LoggerFactory.getLogger(BruteForceTest.class);
+
+    @Test
+    public void testClassLoaderTemplateResolverTxt() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.TEXT);
+        resolver.setCharacterEncoding("UTF-8");
+        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
+        resolver.setSuffix(".txt");
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testClassLoaderTemplateResolverHtml() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.HTML);
+        resolver.setCharacterEncoding("UTF-8");
+        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
+        resolver.setSuffix(".html");
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testClassLoaderTemplateResolverXml() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.XML);
+        resolver.setCharacterEncoding("UTF-8");
+        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
+        resolver.setSuffix(".xml");
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testClassLoaderTemplateResolverHtmlAsXml() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.HTML);
+        resolver.setCharacterEncoding("UTF-8");
+        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
+        resolver.setSuffix(".xml");
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testDefaultTemplateResolverTxt() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        DefaultTemplateResolver resolver = new DefaultTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.TEXT);
+        resolver.setTemplate(textTemplate());
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testDefaultTemplateResolverHtml() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        DefaultTemplateResolver resolver = new DefaultTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.HTML);
+        resolver.setTemplate(textTemplate());
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testFileTemplateResolverTxt() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        FileTemplateResolver resolver = new FileTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.TEXT);
+        resolver.setCharacterEncoding("UTF-8");
+        resolver.setPrefix("src/test/resources/org/apache/camel/component/thymeleaf/");
+        resolver.setSuffix(".txt");
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testFileTemplateResolverHtml() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        FileTemplateResolver resolver = new FileTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.HTML);
+        resolver.setCharacterEncoding("UTF-8");
+        resolver.setPrefix("src/test/resources/org/apache/camel/component/thymeleaf/");
+        resolver.setSuffix(".html");
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testFileTemplateResolverTxtAsHtml() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        FileTemplateResolver resolver = new FileTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.HTML);
+        resolver.setCharacterEncoding("UTF-8");
+        resolver.setPrefix("src/test/resources/org/apache/camel/component/thymeleaf/");
+        resolver.setSuffix(".txt");
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testFileTemplateResolverHtmlAsTxt() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        FileTemplateResolver resolver = new FileTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.TEXT);
+        resolver.setCharacterEncoding("UTF-8");
+        resolver.setPrefix("src/test/resources/org/apache/camel/component/thymeleaf/");
+        resolver.setSuffix(".html");
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testFileTemplateResolverNoMode() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        FileTemplateResolver resolver = new FileTemplateResolver();
+        resolver.setCharacterEncoding("UTF-8");
+        resolver.setPrefix("src/test/resources/org/apache/camel/component/thymeleaf/");
+        resolver.setSuffix(".html");
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testStringTemplateResolverTxt() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        StringTemplateResolver resolver = new StringTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.TEXT);
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(textTemplate(), context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testStringTemplateResolverHtml() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+        StringTemplateResolver resolver = new StringTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.HTML);
+        templateEngine.setTemplateResolver(resolver);
+
+        String result = templateEngine.process(textTemplate(), context());
+        LOG.info("\n" + result.trim());
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    protected Context context() {
+
+        Context context = new Context();
+        context.setVariable("headers", headers());
+        context.setVariable("body", body());
+
+        return context;
+    }
+
+    protected Map<String, Object> headers() {
+
+        Map<String, Object> headers = new HashMap<>();
+        headers.put("lastName", "Doe");
+        headers.put("firstName", "Jane");
+        headers.put("item", "Widgets for Dummies");
+
+        return headers;
+    }
+
+    protected Object body() {
+
+        return "Spazz Testing Service";
+    }
+
+    protected String textTemplate() {
+
+        return """
+                <!--/*-->
+                    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.
+                <!--*/-->
+                <!--/* This code will be removed at thymeleaf parsing time! */-->
+                Dear [(${headers.lastName})], [(${headers.firstName})]
+
+                Thanks for the order of [(${headers.item})].
+
+                Regards Camel Riders Bookstore
+                [(${body})]""";
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceWebAppResolverTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceWebAppResolverTest.java
new file mode 100644
index 00000000000..2c3263e6a2f
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceWebAppResolverTest.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import jakarta.servlet.ServletContext;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.thymeleaf.TemplateEngine;
+import org.thymeleaf.context.Context;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.WebApplicationTemplateResolver;
+import org.thymeleaf.web.servlet.JakartaServletWebApplication;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+
+public class BruteForceWebAppResolverTest {
+
+    private static final String TEMPLATE_NAME = "letter";
+
+    private static final Logger LOG = LoggerFactory.getLogger(BruteForceWebAppResolverTest.class);
+
+    private JakartaServletWebApplication servletWebApplication;
+
+    @BeforeEach
+    public void setUp() throws Exception {
+
+        ServletContext servletContext = mock(ServletContext.class);
+
+        servletWebApplication = JakartaServletWebApplication.buildApplication(servletContext);
+
+        File initialFile = new File("src/test/resources/WEB-INF/templates/letter.html");
+        InputStream targetStream = FileUtils.openInputStream(initialFile);
+        Mockito.when(servletContext.getResourceAsStream(anyString())).thenReturn(targetStream);
+    }
+
+    @Test
+    public void testWebApplicationTemplateResolverHtml() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+
+        WebApplicationTemplateResolver resolver = new WebApplicationTemplateResolver(servletWebApplication);
+        resolver.setTemplateMode(TemplateMode.HTML);
+        resolver.setCharacterEncoding("UTF-8");
+        resolver.setPrefix("/WEB-INF/templates/");
+        resolver.setSuffix(".html");
+
+        templateEngine.addTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.debug("\n" + result);
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    @Test
+    public void testWebApplicationTemplateResolverTxt() {
+
+        TemplateEngine templateEngine = new TemplateEngine();
+
+        WebApplicationTemplateResolver resolver = new WebApplicationTemplateResolver(servletWebApplication);
+        resolver.setTemplateMode(TemplateMode.TEXT);
+        resolver.setCharacterEncoding("UTF-8");
+        resolver.setPrefix("/WEB-INF/templates/");
+        resolver.setSuffix(".html");
+
+        templateEngine.addTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.debug("\n" + result);
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    protected Context context() {
+
+        Context context = new Context();
+        context.setVariable("headers", headers());
+        context.setVariable("body", body());
+
+        return context;
+    }
+
+    protected Object body() {
+
+        return "Spazz Testing Service";
+    }
+
+    protected Map<String, Object> headers() {
+
+        Map<String, Object> headers = new HashMap<>();
+        headers.put("lastName", "Doe");
+        headers.put("firstName", "Jane");
+        headers.put("item", "Widgets for Dummies");
+
+        return headers;
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceWiremockTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceWiremockTest.java
new file mode 100644
index 00000000000..8823c1c7bdc
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/BruteForceWiremockTest.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
+import com.github.tomakehurst.wiremock.junit5.WireMockTest;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.thymeleaf.TemplateEngine;
+import org.thymeleaf.context.Context;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
+import org.thymeleaf.templateresolver.UrlTemplateResolver;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.ok;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@WireMockTest(httpPort = 9843)
+public class BruteForceWiremockTest {
+
+    private static final String TEMPLATE_NAME = "letterWithUrl";
+
+    private static final Logger LOG = LoggerFactory.getLogger(BruteForceWiremockTest.class);
+
+    @Test
+    public void testUrlTemplateResolver(WireMockRuntimeInfo wmRuntimeInfo) {
+
+        stubFor(get("/dontcare.html").willReturn(ok(fragment())));
+
+        TemplateEngine templateEngine = new TemplateEngine();
+
+        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
+        resolver.setTemplateMode(TemplateMode.HTML);
+        resolver.setCharacterEncoding("UTF-8");
+        resolver.setPrefix("/org/apache/camel/component/thymeleaf/");
+        resolver.setSuffix(".html");
+        resolver.setOrder(2);
+
+        UrlTemplateResolver urlTemplateResolver = new UrlTemplateResolver();
+        urlTemplateResolver.setCharacterEncoding("UTF-8");
+        urlTemplateResolver.setOrder(1);
+
+        templateEngine.addTemplateResolver(urlTemplateResolver);
+        templateEngine.addTemplateResolver(resolver);
+
+        String result = templateEngine.process(TEMPLATE_NAME, context());
+        LOG.info("\n" + result);
+
+        assertNotNull(result);
+        assertTrue((result.length() > 0));
+    }
+
+    protected Context context() {
+
+        Context context = new Context();
+        context.setVariable("headers", headers());
+        context.setVariable("body", body());
+
+        return context;
+    }
+
+    protected Object body() {
+
+        return "Spazz Testing Service";
+    }
+
+    protected Map<String, Object> headers() {
+
+        Map<String, Object> headers = new HashMap<>();
+        headers.put("lastName", "Doe");
+        headers.put("firstName", "Jane");
+        headers.put("item", "Widgets for Dummies");
+
+        return headers;
+    }
+
+    protected String fragment() {
+
+        return """
+                <span th:fragment="test" th:remove="tag">
+                You will be notified when your order ships.
+                </span>
+                """;
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/FruitFilter.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/FruitFilter.java
new file mode 100644
index 00000000000..768c6d1db98
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/FruitFilter.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+public class FruitFilter {
+
+    public boolean isApple(String body) {
+
+        return "apple".equalsIgnoreCase(body);
+    }
+
+    public boolean isOrange(String body) {
+
+        return "orange".equalsIgnoreCase(body);
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafAttachmentsTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafAttachmentsTest.java
new file mode 100644
index 00000000000..7e904fe1f66
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafAttachmentsTest.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import jakarta.activation.DataHandler;
+import jakarta.activation.FileDataSource;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.attachment.AttachmentMessage;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+/**
+ * Thymeleaf unit test
+ */
+public class ThymeleafAttachmentsTest extends CamelTestSupport {
+
+    @Test
+    public void testThymeleafAttachments() {
+
+        Exchange exchange = template.request("direct:a", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+
+                exchange.setProperty("item", "7");
+
+                AttachmentMessage am = exchange.getIn(AttachmentMessage.class);
+                am.setBody("Monday");
+                am.setHeader("name", "Christian");
+                am.addAttachment("123", new DataHandler(new FileDataSource("pom.xml")));
+            }
+        });
+
+        assertEquals("Dear Christian. You ordered item 7 on Monday.", exchange.getMessage().getBody());
+        assertEquals("Christian", exchange.getMessage().getHeader("name"));
+
+        AttachmentMessage am = exchange.getMessage(AttachmentMessage.class);
+        assertNotNull(am);
+        assertEquals("123", am.getAttachmentNames().iterator().next());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+                // START SNIPPET: example
+                from("direct:a").to(
+                        "thymeleaf:org/apache/camel/component/thymeleaf/example.txt?allowTemplateFromHeader=true&allowContextMapAll=true");
+                // END SNIPPET: example
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafBodyAsDomainObjectTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafBodyAsDomainObjectTest.java
new file mode 100644
index 00000000000..780212e8e05
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafBodyAsDomainObjectTest.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.component.thymeleaf;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Unit test with the body as a Domain object.
+ */
+public class ThymeleafBodyAsDomainObjectTest extends CamelTestSupport {
+
+    @Test
+    public void testWithObject() throws Exception {
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        mock.message(0).body().contains("Hi Claus how are you? Its a nice day.");
+
+        MyPerson person = new MyPerson();
+        person.setFamilyName("Ibsen");
+        person.setGivenName("Claus");
+
+        template.requestBody("direct:in", person);
+
+        mock.assertIsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+
+                from("direct:in")
+                        .to("thymeleaf:org/apache/camel/component/thymeleaf/BodyAsDomainObject.txt")
+                        .to("mock:result");
+            }
+        };
+    }
+
+    public static class MyPerson {
+
+        private String givenName;
+
+        private String familyName;
+
+        public String getGivenName() {
+
+            return givenName;
+        }
+
+        public void setGivenName(String givenName) {
+
+            this.givenName = givenName;
+        }
+
+        public String getFamilyName() {
+
+            return familyName;
+        }
+
+        public void setFamilyName(String familyName) {
+
+            this.familyName = familyName;
+        }
+
+        @Override
+        public String toString() {
+
+            return "MyPerson{"
+                   + "givenName='"
+                   + givenName + '\''
+                   + ", familyName='"
+                   + familyName + '\''
+                   + '}';
+        }
+
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafConcurrentTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafConcurrentTest.java
new file mode 100644
index 00000000000..deeb950f10b
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafConcurrentTest.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.component.thymeleaf;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.camel.test.junit5.TestSupport.body;
+
+public class ThymeleafConcurrentTest extends CamelTestSupport {
+
+    @Test
+    public void testNoConcurrentProducers() throws Exception {
+
+        doSendMessages(1, 1);
+    }
+
+    @Test
+    public void testConcurrentProducers() throws Exception {
+
+        doSendMessages(10, 5);
+    }
+
+    private void doSendMessages(int files, int poolSize) throws Exception {
+
+        getMockEndpoint("mock:result").expectedMessageCount(files);
+        getMockEndpoint("mock:result").assertNoDuplicates(body());
+        getMockEndpoint("mock:result").message(0).body().contains("Bye");
+
+        ExecutorService executor = Executors.newFixedThreadPool(poolSize);
+        for (int i = 0; i < files; i++) {
+            final int index = i;
+            executor.submit(new Callable<Object>() {
+
+                public Object call() {
+
+                    template.sendBody("direct:start", "Hello " + index);
+                    return null;
+                }
+            });
+        }
+
+        MockEndpoint.assertIsSatisfied(context);
+        executor.shutdownNow();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+
+                from("direct:start").to("thymeleaf:org/apache/camel/component/thymeleaf/Concurrent.txt").to("mock:result");
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafContentCacheTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafContentCacheTest.java
new file mode 100644
index 00000000000..7d0bf7c3465
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafContentCacheTest.java
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import java.util.ArrayList;
+import java.util.Set;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Unit test the cache when reloading .ftl files in the classpath
+ */
+public class ThymeleafContentCacheTest extends CamelTestSupport {
+
+    @Override
+    public boolean useJmx() {
+
+        return true;
+    }
+
+    @Override
+    @BeforeEach
+    public void setUp() throws Exception {
+
+        super.setUp();
+
+        // create a vm file in the classpath as this is the tricky reloading stuff
+        template.sendBodyAndHeader("file://target/test-classes/org/apache/camel/component/thymeleaf?fileExist=Override",
+                "Hello ${headers.name}", Exchange.FILE_NAME, "hello.ftl");
+    }
+
+    @Test
+    public void testNotCached() throws Exception {
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedBodiesReceived("Hello London");
+
+        template.sendBodyAndHeader("direct:a", "Body", "name", "London");
+        mock.assertIsSatisfied();
+
+        // now change content in the file in the classpath and try again
+        template.sendBodyAndHeader("file://target/test-classes/org/apache/camel/component/thymeleaf?fileExist=Override",
+                "Bye ${headers.name}", Exchange.FILE_NAME, "hello.ftl");
+
+        mock.reset();
+        mock.expectedBodiesReceived("Bye Paris");
+
+        template.sendBodyAndHeader("direct:a", "Body", "name", "Paris");
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    public void testCached() throws Exception {
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedBodiesReceived("Hello London");
+
+        template.sendBodyAndHeader("direct:b", "Body", "name", "London");
+        mock.assertIsSatisfied();
+
+        // now change content in the file in the classpath and try again
+        template.sendBodyAndHeader("file://target/test-classes/org/apache/camel/component/thymeleaf?fileExist=Override",
+                "Bye ${headers.name}", Exchange.FILE_NAME, "hello.ftl");
+
+        mock.reset();
+        // we must expected the original filecontent as the cache is enabled, so its Hello and not Bye
+        mock.expectedBodiesReceived("Hello Paris");
+
+        template.sendBodyAndHeader("direct:b", "Body", "name", "Paris");
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    public void testTemplateUpdateDelay() throws Exception {
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedBodiesReceived("Hello London");
+
+        template.sendBodyAndHeader("direct:c", "Body", "name", "London");
+        mock.assertIsSatisfied();
+
+        // now change content in the file in the classpath and try again .... with no delay
+        template.sendBodyAndHeader("file://target/test-classes/org/apache/camel/component/thymeleaf?fileExist=Override",
+                "Bye ${headers.name}", Exchange.FILE_NAME, "hello.ftl");
+
+        mock.reset();
+        // we must expected the original filecontent as the cache is enabled, so its Hello and not Bye
+        mock.expectedBodiesReceived("Hello Paris");
+
+        template.sendBodyAndHeader("direct:c", "Body", "name", "Paris");
+        mock.assertIsSatisfied();
+
+        // now change content in the file in the classpath and try again .... after delaying longer than the cache update delay
+        Thread.sleep(2000);
+        template.sendBodyAndHeader("file://target/test-classes/org/apache/camel/component/thymeleaf?fileExist=Override",
+                "Bye ${headers.name}", Exchange.FILE_NAME, "hello.ftl");
+
+        mock.reset();
+        // we must expected the new content, because the cache has expired
+        mock.expectedBodiesReceived("Bye Paris");
+        template.sendBodyAndHeader("direct:c", "Body", "name", "Paris");
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    public void testClearCacheViaJmx() throws Exception {
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedBodiesReceived("Hello London");
+
+        template.sendBodyAndHeader("direct:b", "Body", "name", "London");
+        mock.assertIsSatisfied();
+
+        // now change content in the file in the classpath and try again
+        template.sendBodyAndHeader("file://target/test-classes/org/apache/camel/component/thymeleaf?fileExist=Override",
+                "Bye ${headers.name}", Exchange.FILE_NAME, "hello.ftl");
+
+        mock.reset();
+        // we must expected the original filecontent as the cache is enabled, so its Hello and not Bye
+        mock.expectedBodiesReceived("Hello Paris");
+
+        template.sendBodyAndHeader("direct:b", "Body", "name", "Paris");
+        mock.assertIsSatisfied();
+
+        // clear the cache via the mbean server
+        MBeanServer mbeanServer = context.getManagementStrategy().getManagementAgent().getMBeanServer();
+        Set<ObjectName> objNameSet = mbeanServer
+                .queryNames(new ObjectName("org.apache.camel:type=endpoints,name=\"thymeleaf:*contentCache=true*\",*"), null);
+        ObjectName managedObjName = new ArrayList<>(objNameSet).get(0);
+        mbeanServer.invoke(managedObjName, "clearContentCache", null, null);
+
+        // change content in the file in the classpath and try again
+        template.sendBodyAndHeader("file://target/test-classes/org/apache/camel/component/thymeleaf?fileExist=Override",
+                "Bye ${headers.name}", Exchange.FILE_NAME, "hello.ftl");
+        mock.reset();
+        // we expect the updated file content because the cache was cleared
+        mock.expectedBodiesReceived("Bye Paris");
+        template.sendBodyAndHeader("direct:b", "Body", "name", "Paris");
+        mock.assertIsSatisfied();
+
+        // change content in the file in the classpath and try again to verify that the caching is still in effect after clearing the cache
+        template.sendBodyAndHeader("file://target/test-classes/org/apache/camel/component/thymeleaf?fileExist=Override",
+                "Hello ${headers.name}", Exchange.FILE_NAME, "hello.ftl");
+        mock.reset();
+        // we expect the cached content from the prior update
+        mock.expectedBodiesReceived("Bye Paris");
+        template.sendBodyAndHeader("direct:b", "Body", "name", "Paris");
+        mock.assertIsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+
+                from("direct:a").to("thymeleaf://org/apache/camel/component/thymeleaf/hello.ftl?contentCache=false")
+                        .to("mock:result");
+
+                from("direct:b").to("thymeleaf://org/apache/camel/component/thymeleaf/hello.ftl?contentCache=true")
+                        .to("mock:result");
+
+                from("direct:c").to(
+                        "thymeleaf://org/apache/camel/component/thymeleaf/hello.ftl?contentCache=true&templateUpdateDelay=1")
+                        .to("mock:result");
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafEncodingTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafEncodingTest.java
new file mode 100644
index 00000000000..ee43bea9aeb
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafEncodingTest.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import org.apache.camel.builder.RouteBuilder;
+
+public class ThymeleafEncodingTest extends ThymeleafLetterTest {
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+
+                from("direct:a").to("thymeleaf:org/apache/camel/component/thymeleaf/letter-utf16.txt?encoding=UTF-16")
+                        .to("mock:result");
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointTest.java
new file mode 100644
index 00000000000..bbaf243029d
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafEndpointTest.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import org.apache.camel.builder.RouteBuilder;
+
+/**
+ * Thymeleaf unit test
+ */
+public class ThymeleafEndpointTest extends ThymeleafTest {
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() throws Exception {
+
+                ThymeleafEndpoint endpoint = new ThymeleafEndpoint();
+                endpoint.setCamelContext(context);
+                endpoint.setAllowTemplateFromHeader(true);
+                endpoint.setAllowContextMapAll(true);
+                endpoint.setResourceUri("org/apache/camel/component/thymeleaf/example.txt");
+
+                context.addEndpoint("free", endpoint);
+
+                from("direct:a").to("free");
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafFileLetterTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafFileLetterTest.java
new file mode 100644
index 00000000000..977a2778975
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafFileLetterTest.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import org.apache.camel.builder.RouteBuilder;
+
+public class ThymeleafFileLetterTest extends ThymeleafLetterTest {
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+
+                from("direct:a")
+                        .to("thymeleaf:file:src/test/resources/org/apache/camel/component/thymeleaf/letter.txt")
+                        .to("mock:result");
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafLetterTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafLetterTest.java
new file mode 100644
index 00000000000..361d49a052d
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafLetterTest.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.component.thymeleaf;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Unit test for wiki documentation
+ */
+public class ThymeleafLetterTest extends CamelTestSupport {
+
+    // START SNIPPET: e1
+    private Exchange createLetter() {
+
+        Exchange exchange = context.getEndpoint("direct:a").createExchange();
+
+        Message msg = exchange.getIn();
+        msg.setHeader("firstName", "Claus");
+        msg.setHeader("lastName", "Ibsen");
+        msg.setHeader("item", "Camel in Action");
+        msg.setBody("PS: Next beer is on me, James");
+
+        return exchange;
+    }
+
+    @Test
+    public void testThymeleafLetter() throws Exception {
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        mock.message(0).body().contains("Dear Ibsen, Claus");
+        mock.message(0).body().contains("Thanks for the order of Camel in Action.");
+
+        template.send("direct:a", createLetter());
+
+        mock.assertIsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+                context.setTracing(true);
+
+                from("direct:a")
+                        .to("thymeleaf:org/apache/camel/component/thymeleaf/letter.txt")
+                        .to("mock:result");
+            }
+        };
+    }
+    // END SNIPPET: e1
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafLetterWithoutHeaderTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafLetterWithoutHeaderTest.java
new file mode 100644
index 00000000000..c3dd7016f46
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafLetterWithoutHeaderTest.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import org.apache.camel.builder.RouteBuilder;
+
+public class ThymeleafLetterWithoutHeaderTest extends ThymeleafLetterTest {
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+
+                from("direct:a").to("thymeleaf:org/apache/camel/component/thymeleaf/header.txt")
+                        .to("thymeleaf:org/apache/camel/component/thymeleaf/letterWithoutHeader.txt").to("mock:result");
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafOverrideHeaderTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafOverrideHeaderTest.java
new file mode 100644
index 00000000000..ffbf076fec0
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafOverrideHeaderTest.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class ThymeleafOverrideHeaderTest extends CamelTestSupport {
+
+    @Override
+    public boolean isUseRouteBuilder() {
+
+        return false;
+    }
+
+    private Exchange createLetter() {
+
+        Exchange exchange = context.getEndpoint("direct:a").createExchange();
+
+        Message msg = exchange.getIn();
+        msg.setHeader("firstName", "Claus");
+        msg.setHeader("lastName", "Ibsen");
+        msg.setHeader("item", "Camel in Action");
+        msg.setBody("PS: Next beer is on me, James");
+        msg.setHeader(ThymeleafConstants.THYMELEAF_RESOURCE_URI, "org/apache/camel/component/thymeleaf/letter.txt");
+        return exchange;
+    }
+
+    @Test
+    public void testThymeleafLetter() throws Exception {
+
+        context.addRoutes(new RouteBuilder() {
+
+            @Override
+            public void configure() {
+
+                from("direct:a")
+                        .to("thymeleaf:org/apache/camel/component/thymeleaf/example.txt")
+                        .to("mock:result");
+            }
+        });
+        context.start();
+
+        Exchange out = template.send("direct:a", createLetter());
+        assertTrue(out.isFailed());
+
+        context.stop();
+    }
+
+    @Test
+    public void testThymeleafLetterAllowed() throws Exception {
+
+        context.addRoutes(new RouteBuilder() {
+
+            @Override
+            public void configure() {
+
+                from("direct:a")
+                        .to("thymeleaf:org/apache/camel/component/thymeleaf/example.txt?allowTemplateFromHeader=true")
+                        .to("mock:result");
+            }
+        });
+        context.start();
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        mock.message(0).body().contains("Dear Ibsen, Claus");
+        mock.message(0).body().contains("Thanks for the order of Camel in Action.");
+
+        template.send("direct:a", createLetter());
+
+        mock.assertIsSatisfied();
+
+        context.stop();
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafSetHeaderTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafSetHeaderTest.java
new file mode 100644
index 00000000000..b65a134160f
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafSetHeaderTest.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.Processor;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.spring.junit5.CamelSpringTestSupport;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class ThymeleafSetHeaderTest extends CamelSpringTestSupport {
+
+    @Test
+    public void testSendingApple() throws Exception {
+
+        assertRespondsWith("apple", "I am an apple");
+    }
+
+    @Test
+    public void testSendingOrgane() throws Exception {
+
+        assertRespondsWith("orange", "I am an orange");
+    }
+
+    protected void assertRespondsWith(final String value, String expectedBody) throws Exception {
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        //mock.expectedHeaderReceived("fruit", value);
+        mock.expectedBodiesReceived(expectedBody);
+        template.request("direct:start", new Processor() {
+
+            public void process(Exchange exchange) {
+
+                Message in = exchange.getIn();
+                in.setBody(value);
+            }
+        });
+        mock.assertIsSatisfied();
+    }
+
+    @Override
+    protected ClassPathXmlApplicationContext createApplicationContext() {
+
+        return new ClassPathXmlApplicationContext("org/apache/camel/component/thymeleaf/camel-context.xml");
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafTemplateInHeaderTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafTemplateInHeaderTest.java
new file mode 100644
index 00000000000..60842117bbc
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafTemplateInHeaderTest.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.InvalidPayloadException;
+import org.apache.camel.Message;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.camel.test.junit5.TestSupport.assertMessageBodyEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class ThymeleafTemplateInHeaderTest extends CamelTestSupport {
+
+    @Test
+    public void testReceivesFooResponse() throws Exception {
+
+        assertRespondsWith("cheese", "foo", "<hello>foo</hello>");
+    }
+
+    @Test
+    public void testReceivesBarResponse() throws Exception {
+
+        assertRespondsWith("cheese", "bar", "<hello>bar</hello>");
+    }
+
+    @Test
+    public void testRespectHeaderNamesUpperCase() throws Exception {
+
+        assertRespondsWith("Cheese", "bar", "<hello>bar</hello>");
+    }
+
+    @Test
+    public void testRespectHeaderNamesCamelCase() throws Exception {
+
+        assertRespondsWith("CorrelationID", "bar", "<hello>bar</hello>");
+    }
+
+    protected void assertRespondsWith(final String headerName, final String headerValue, String expectedBody)
+            throws InvalidPayloadException {
+
+        Exchange response = template.request("direct:a", new Processor() {
+
+            public void process(Exchange exchange) {
+
+                Message in = exchange.getIn();
+                in.setHeader(ThymeleafConstants.THYMELEAF_TEMPLATE, "<hello>${headers." + headerName + "}</hello>");
+                in.setHeader(headerName, headerValue);
+            }
+        });
+        assertMessageBodyEquals(response, expectedBody);
+
+        Object template = response.getMessage().getHeader(ThymeleafConstants.THYMELEAF_TEMPLATE);
+        assertNull(template, "Template header should have been removed");
+
+        Set<Entry<String, Object>> entrySet = response.getMessage().getHeaders().entrySet();
+        boolean keyFound = false;
+        for (Entry<String, Object> entry : entrySet) {
+            if (entry.getKey().equals(headerName)) {
+                keyFound = true;
+                break;
+            }
+        }
+        assertTrue(keyFound, "Header should been found");
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+
+                from("direct:a").to("thymeleaf://dummy?allowTemplateFromHeader=true");
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafTest.java
new file mode 100644
index 00000000000..852520813e6
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafTest.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Thymeleaf unit test
+ */
+public class ThymeleafTest extends CamelTestSupport {
+
+    @Test
+    public void testThymeleafLetter() {
+
+        Exchange exchange = template.request("direct:a", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+
+                exchange.getIn().setBody("Monday");
+                exchange.getIn().setHeader("name", "Christian");
+                exchange.setProperty("item", "7");
+            }
+        });
+
+        assertEquals("Dear Christian. You ordered item 7 on Monday.", exchange.getMessage().getBody());
+        assertEquals("Christian", exchange.getMessage().getHeader("name"));
+    }
+
+    @Test
+    public void testThymeleafDataModel() {
+
+        Exchange exchange = template.request("direct:a", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+
+                exchange.getIn().setBody("");
+                exchange.getIn().setHeader("name", "Christian");
+                Map<String, Object> variableMap = new HashMap<>();
+                Map<String, Object> headersMap = new HashMap<>();
+                headersMap.put("name", "Willem");
+                variableMap.put("headers", headersMap);
+                variableMap.put("body", "Monday");
+                variableMap.put("exchange", exchange);
+                exchange.getIn().setHeader(ThymeleafConstants.THYMELEAF_VARIABLE_MAP, variableMap);
+                exchange.setProperty("item", "7");
+            }
+        });
+
+        assertEquals("Dear Willem. You ordered item 7 on Monday.", exchange.getMessage().getBody());
+        assertEquals("Christian", exchange.getMessage().getHeader("name"));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+                // START SNIPPET: example
+                from("direct:a").to(
+                        "thymeleaf:org/apache/camel/component/thymeleaf/example.txt?allowTemplateFromHeader=true&allowContextMapAll=true");
+                // END SNIPPET: example
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafValuesInPropertiesTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafValuesInPropertiesTest.java
new file mode 100644
index 00000000000..5183f3b5457
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafValuesInPropertiesTest.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.thymeleaf;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+public class ThymeleafValuesInPropertiesTest extends CamelTestSupport {
+
+    @EndpointInject("mock:result")
+    private MockEndpoint mock;
+
+    @Test
+    public void testThymeleafLetter() throws Exception {
+
+        mock.expectedBodiesReceived("Dear Christian. You ordered item 7.");
+
+        template.send("direct:a", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+
+                exchange.getIn().setHeader(ThymeleafConstants.THYMELEAF_TEMPLATE,
+                        "Dear ${exchange.properties.name}. You ordered item ${exchange.properties.item}.");
+                exchange.setProperty("name", "Christian");
+                exchange.setProperty("item", "7");
+            }
+        });
+
+        mock.assertIsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+
+        return new RouteBuilder() {
+
+            public void configure() {
+
+                ThymeleafComponent fc = context.getComponent("thymeleaf", ThymeleafComponent.class);
+                fc.setAllowTemplateFromHeader(true);
+                fc.setAllowContextMapAll(true);
+
+                from("direct:a")
+                        .to("thymeleaf:dummy")
+                        .to("mock:result");
+            }
+        };
+    }
+
+}
diff --git a/components/camel-thymeleaf/src/test/resources/WEB-INF/templates/letter.html b/components/camel-thymeleaf/src/test/resources/WEB-INF/templates/letter.html
new file mode 100644
index 00000000000..0023e1d2877
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/resources/WEB-INF/templates/letter.html
@@ -0,0 +1,24 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+Dear [[${headers.lastName}]], [[${headers.firstName}]]
+
+Thanks for the order of [[${headers.item}]].
+
+Regards Camel Riders Bookstore
+[[${body}]]
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/log4j2.properties b/components/camel-thymeleaf/src/test/resources/log4j2.properties
new file mode 100644
index 00000000000..88a74e81ca1
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/resources/log4j2.properties
@@ -0,0 +1,32 @@
+## ---------------------------------------------------------------------------
+## 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.out.type = File
+appender.out.name = out
+appender.out.fileName = target/camel-thymeleaf-test.log
+appender.out.layout.type = PatternLayout
+appender.out.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+appender.stdout.type = Console
+appender.stdout.name = stdout
+appender.stdout.layout.type = PatternLayout
+appender.stdout.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+rootLogger.level = INFO
+rootLogger.appenderRef.out.ref = out
+rootLogger.appenderRef.stdout.ref = stdout
+logger.thymeleaf.name = org.apache.camel.component.thymeleaf
+logger.thymeleaf.level = DEBUG
+
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/AppleTemplate.txt b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/AppleTemplate.txt
new file mode 100644
index 00000000000..c8d3ac0f493
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/AppleTemplate.txt
@@ -0,0 +1,19 @@
+<#--
+
+    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.
+
+-->
+${request.setHeader('fruit', 'apple')}I am an ${body}
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/BodyAsDomainObject.txt b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/BodyAsDomainObject.txt
new file mode 100644
index 00000000000..7648c82b5f2
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/BodyAsDomainObject.txt
@@ -0,0 +1,20 @@
+<#--
+
+    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.
+
+-->
+Hi ${body.givenName} how are you? Its a nice day.
+Give my regards to the family ${body.familyName}.
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/Concurrent.txt b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/Concurrent.txt
new file mode 100644
index 00000000000..5736a335f88
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/Concurrent.txt
@@ -0,0 +1,19 @@
+<#--
+
+    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.
+
+-->
+Bye ${body}
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/OrangeTemplate.txt b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/OrangeTemplate.txt
new file mode 100644
index 00000000000..0a76babaf81
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/OrangeTemplate.txt
@@ -0,0 +1,19 @@
+<#--
+
+    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.
+
+-->
+${request.setHeader('fruit', 'orange')}I am an ${body}
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/camel-context.xml b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/camel-context.xml
new file mode 100644
index 00000000000..c1646cf5b70
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/camel-context.xml
@@ -0,0 +1,44 @@
+<?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">
+
+  <camelContext xmlns="http://camel.apache.org/schema/spring">
+    <route>
+	   	<from uri="direct:start"/>
+	    <filter>
+	   		<method ref="fruitFilter" method="isApple"/>
+        	<to uri="thymeleaf:org/apache/camel/component/thymeleaf/AppleTemplate.ftl?allowContextMapAll=true" />
+        	<to uri="mock:result" />
+	    </filter>
+	    <filter>
+	   		<method ref="fruitFilter" method="isOrange"/>
+        	<to uri="thymeleaf:org/apache/camel/component/thymeleaf/OrangeTemplate.ftl?allowContextMapAll=true" />
+    	    <to uri="mock:result" />
+	    </filter>
+   </route>
+  </camelContext>
+
+  <bean id="fruitFilter" class="org.apache.camel.component.thymeleaf.FruitFilter"/>
+  
+</beans>
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/example.txt b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/example.txt
new file mode 100644
index 00000000000..b7e6e721a68
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/example.txt
@@ -0,0 +1,19 @@
+<#--
+
+    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.
+
+-->
+Dear ${headers.name}. You ordered item ${exchange.properties.item} on ${body}.
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/header.txt b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/header.txt
new file mode 100644
index 00000000000..666463f16b0
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/header.txt
@@ -0,0 +1,19 @@
+<#--
+
+    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.
+
+-->
+Dear ${headers.lastName}, ${headers.firstName}
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter-utf16.txt b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter-utf16.txt
new file mode 100644
index 00000000000..d435ae55e98
Binary files /dev/null and b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter-utf16.txt differ
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.css b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.css
new file mode 100644
index 00000000000..9d4c33de3f2
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.css
@@ -0,0 +1,40 @@
+/**
+ * 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.
+ */
+<!--/*
+    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.
+
+    Comments are not supported in CSS templates, so this ASF header will appear in the rendered text.
+*/-->
+# just a comment
+.fixed_header tbody {
+    display: /*[(${headers.display})]*/ inline;
+    overflow: auto;
+    height: /*[(${headers.height})]*/ 1.0em;
+}
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.html b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.html
new file mode 100644
index 00000000000..0023e1d2877
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.html
@@ -0,0 +1,24 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+Dear [[${headers.lastName}]], [[${headers.firstName}]]
+
+Thanks for the order of [[${headers.item}]].
+
+Regards Camel Riders Bookstore
+[[${body}]]
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.js b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.js
new file mode 100644
index 00000000000..90ca6984c27
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.js
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+<!--/*
+    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.
+
+    Comments are not supported in JAVASCRIPT templates, so this ASF header will appear in the rendered text.
+*/-->
+<span th:fragment="show-hide-content" th:remove="tag">
+    <script th:inline="javascript">
+        function hideContent() {
+            showContentButton = document.getElementById(/*[[${headers.showContentButton}]]*/ 'showContentButton');
+            hideContentButton = document.getElementById(/*[[${headers.hideContentButton}]]*/ 'hideContentButton');
+            someContent = document.getElementById(/*[[${body}]]*/ 'someContent');
+
+            showContentButton.style.display = 'block';
+            hideContentButton.style.display = 'none';
+            someContent.style.display = 'none';
+        }
+
+        function showContent() {
+            showContentButton = document.getElementById(/*[[${headers.showContentButton}]]*/ 'showContentButton');
+            hideContentButton = document.getElementById(/*[[${headers.hideContentButton}]]*/ 'hideContentButton');
+            someContent = document.getElementById(/*[[${body}]]*/ 'someContent');
+
+            showContentButton.style.display = 'none';
+            hideContentButton.style.display = 'block';
+            someContent.style.display = 'block';
+        }
+    </script>
+</span>
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.txt b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.txt
new file mode 100644
index 00000000000..2a2e9ae4b0f
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.txt
@@ -0,0 +1,25 @@
+<!--/*-->
+    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.
+
+    Comments are not supported in TXT templates, so this ASF header will appear in the rendered text.
+<!--*/-->
+<!--/* This code will be removed at thymeleaf parsing time! */-->
+Dear [(${headers.lastName})], [(${headers.firstName})]
+
+Thanks for the order of [(${headers.item})].
+
+Regards Camel Riders Bookstore
+[(${body})]
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.xml b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.xml
new file mode 100644
index 00000000000..3355c6c3a52
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letter.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<letter>
+    <greeting>
+        Dear [[${headers.lastName}]], [[${headers.firstName}]]
+    </greeting>
+    <message>
+        Thanks for the order of [[${headers.item}]].
+    </message>
+    <closing>
+        Regards Camel Riders Bookstore
+    </closing>
+    <signature th:attr="content=${body}">
+        1 Jupiter Road, Junit, CA 98765
+    </signature>
+</letter>
+
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letterWithUrl.html b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letterWithUrl.html
new file mode 100644
index 00000000000..66801707d43
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letterWithUrl.html
@@ -0,0 +1,24 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+Dear [[${headers.lastName}]], [[${headers.firstName}]]
+
+Thanks for the order of [[${headers.item}]].
+<span th:replace="~{http://localhost:9843/dontcare.html :: test}"/>
+Regards Camel Riders Bookstore
+[[${body}]]
\ No newline at end of file
diff --git a/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letterWithoutHeader.txt b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letterWithoutHeader.txt
new file mode 100644
index 00000000000..3c9f6ca851b
--- /dev/null
+++ b/components/camel-thymeleaf/src/test/resources/org/apache/camel/component/thymeleaf/letterWithoutHeader.txt
@@ -0,0 +1,24 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+${body}
+
+Thanks for the order of ${headers.item}.
+
+Regards Camel Riders Bookstore
+PS: Next beer is on me, James
\ No newline at end of file


[camel] 05/10: Working on unit tests

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 63f9f1f90904313c62331645b7e1e810b0dc57cc
Author: Craig Ziesman <cz...@redhat.com>
AuthorDate: Wed Sep 6 19:52:50 2023 -0500

    Working on unit tests
---
 bom/camel-bom/pom.xml               | 5 +++++
 catalog/camel-allcomponents/pom.xml | 5 +++++
 2 files changed, 10 insertions(+)

diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml
index 7373b9bd110..a3323038652 100644
--- a/bom/camel-bom/pom.xml
+++ b/bom/camel-bom/pom.xml
@@ -1897,6 +1897,11 @@
         <artifactId>camel-thrift</artifactId>
         <version>${project.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-thymeleaf</artifactId>
+        <version>${project.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.apache.camel</groupId>
         <artifactId>camel-tika</artifactId>
diff --git a/catalog/camel-allcomponents/pom.xml b/catalog/camel-allcomponents/pom.xml
index f10a1100107..d717cc7aca9 100644
--- a/catalog/camel-allcomponents/pom.xml
+++ b/catalog/camel-allcomponents/pom.xml
@@ -1677,6 +1677,11 @@
             <artifactId>camel-thrift</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-thymeleaf</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-tika</artifactId>


[camel] 03/10: Initial commit of camel-thymeleaf

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 93fdb2e32f11b977104e9e1084fd9597958c86e6
Author: Craig Ziesman <cz...@redhat.com>
AuthorDate: Mon Aug 28 13:19:15 2023 -0500

    Initial commit of camel-thymeleaf
---
 components/pom.xml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/components/pom.xml b/components/pom.xml
index 0e3ad6d6981..dfc606fba90 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -294,6 +294,7 @@
         <module>camel-telegram</module>
         <module>camel-threadpoolfactory-vertx</module>
         <module>camel-thrift</module>
+        <module>camel-thymeleaf</module>
         <module>camel-tika</module>
         <module>camel-twilio</module>
         <module>camel-twitter</module>


[camel] 07/10: Working on unit tests

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit f87e6c155274cee1ccd438921926316fcf896c07
Author: Craig Ziesman <cz...@redhat.com>
AuthorDate: Thu Sep 7 17:32:26 2023 -0500

    Working on unit tests
---
 components/camel-thymeleaf/pom.xml                 | 72 +---------------------
 .../src/main/docs/thymeleaf-component.adoc         | 24 ++++----
 .../thymeleaf/ThymeleafAbstractBaseTest.java       | 18 +++---
 .../thymeleaf/ThymeleafBodyAsDomainObjectTest.java | 10 +--
 .../thymeleaf/ThymeleafComponentTest.java          |  8 +--
 .../thymeleaf/ThymeleafConcurrentTest.java         |  6 +-
 .../thymeleaf/ThymeleafContentCacheTest.java       | 15 +++--
 .../ThymeleafFileResolverAllParamsTest.java        |  1 -
 ...ymeleafWebApplicationResolverAllParamsTest.java |  9 +--
 .../ThymeleafWebApplicationResolverTest.java       |  7 ++-
 .../src/test/resources/log4j2.properties           |  2 +-
 11 files changed, 51 insertions(+), 121 deletions(-)

diff --git a/components/camel-thymeleaf/pom.xml b/components/camel-thymeleaf/pom.xml
index 736f9e36fb2..e0c503f3ae8 100644
--- a/components/camel-thymeleaf/pom.xml
+++ b/components/camel-thymeleaf/pom.xml
@@ -32,15 +32,6 @@
     <name>Camel :: Thymeleaf</name>
     <description>Camel Thymeleaf support</description>
 
-    <properties>
-        <thymeleaf-version>3.1.2.RELEASE</thymeleaf-version>
-        <jakarta-servlet-api-version>6.0.0</jakarta-servlet-api-version>
-        <wiremock-version>3.0.0-beta-15</wiremock-version>
-        <pitest-maven-version>1.14.4</pitest-maven-version>
-        <pitest-junit5-plugin-version>1.2.0</pitest-junit5-plugin-version>
-        <jacoco-maven-plugin-version>0.8.10</jacoco-maven-plugin-version>
-    </properties>
-
     <dependencies>
         <dependency>
             <groupId>org.apache.camel</groupId>
@@ -76,7 +67,7 @@
         </dependency>
 
         <dependency>
-            <groupId>org.wiremock</groupId>
+            <groupId>com.github.tomakehurst</groupId>
             <artifactId>wiremock</artifactId>
             <version>${wiremock-version}</version>
             <scope>test</scope>
@@ -97,65 +88,4 @@
 
     </dependencies>
 
-    <build>
-        <plugins>
-            <plugin>
-                <artifactId>maven-surefire-plugin</artifactId>
-                <configuration>
-                    <argLine>${argLine}</argLine>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.jacoco</groupId>
-                <artifactId>jacoco-maven-plugin</artifactId>
-                <version>${jacoco-maven-plugin-version}</version>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>prepare-agent</goal>
-                        </goals>
-                    </execution>
-                    <execution>
-                        <id>generate-code-coverage-report</id>
-                        <goals>
-                            <goal>report</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <configuration>
-                    <excludes>
-                        <exclude>**/*Configurer.class</exclude>
-                        <exclude>**/*Factory.class</exclude>
-                    </excludes>
-                </configuration>
-            </plugin>
-
-            <plugin>
-                <groupId>org.pitest</groupId>
-                <artifactId>pitest-maven</artifactId>
-                <version>${pitest-maven-version}</version>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.pitest</groupId>
-                        <artifactId>pitest-junit5-plugin</artifactId>
-                        <version>${pitest-junit5-plugin-version}</version>
-                    </dependency>
-                </dependencies>
-                <configuration>
-                    <targetClasses>
-                        <param>org.apache.camel.component.thymeleaf.*</param>
-                    </targetClasses>
-<!--                    <targetTests>-->
-<!--                        <param>org.apache.camel.component.thymeleaf.*</param>-->
-<!--                    </targetTests>-->
-                    <excludedClasses>
-                        <param>org.apache.camel.component.thymeleaf.*Configurer*</param>
-                        <param>org.apache.camel.component.thymeleaf.*Factory*</param>
-                    </excludedClasses>
-                </configuration>
-            </plugin>
-
-        </plugins>
-    </build>
-
 </project>
diff --git a/components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc b/components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc
index a35288f720a..4694bb40f1b 100644
--- a/components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc
+++ b/components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc
@@ -39,7 +39,7 @@ thymeleaf:templateName[?options]
 
 Where *templateName* is the classpath-local URI of the template to
 invoke; or the complete URL of the remote template (eg:
-\file://folder/myfile.txt).
+\file://folder/myfile.html).
 
 
 
@@ -66,7 +66,7 @@ and added as headers, thus making it possible to return values from
 Thymeleaf to the Message.
 
 For example, to set the header value of `fruit` in the Thymeleaf template
-`fruit-template.txt`:
+`fruit-template.html`:
 
 -------------------------------
 $in.setHeader("fruit", "Apple")
@@ -143,7 +143,7 @@ For a simple use case, you could use something like:
 [source,java]
 ----------------------------------------
 from("activemq:My.Queue").
-  to("thymeleaf:com/acme/MyResponse.txt");
+  to("thymeleaf:com/acme/MyResponse.html");
 ----------------------------------------
 
 To use a Thymeleaf template to formulate a response to a message for
@@ -155,17 +155,17 @@ destination, you could use the following route:
 [source,java]
 ----------------------------------------
 from("activemq:My.Queue")
-  .to("thymeleaf:com/acme/MyResponse.txt")
+  .to("thymeleaf:com/acme/MyResponse.html")
   .to("activemq:Another.Queue");
 ----------------------------------------
 
 And to use the content cache, e.g. for use in production, where the
-`.txt` template never changes:
+`.html` template never changes:
 
 [source,java]
 ----------------------------------------------------------
 from("activemq:My.Queue")
-  .to("thymeleaf:com/acme/MyResponse.txt?contentCache=true")
+  .to("thymeleaf:com/acme/MyResponse.html?contentCache=true")
   .to("activemq:Another.Queue");
 ----------------------------------------------------------
 
@@ -174,7 +174,7 @@ And a file based resource:
 [source,java]
 -----------------------------------------------------------------
 from("activemq:My.Queue")
-  .to("thymeleaf:file://myfolder/MyResponse.txt?contentCache=true")
+  .to("thymeleaf:file://myfolder/MyResponse.html?contentCache=true")
   .to("activemq:Another.Queue");
 -----------------------------------------------------------------
 
@@ -184,7 +184,7 @@ should use dynamically via a header, so for example:
 [source,java]
 ---------------------------------------------------------------------------
 from("direct:in")
-  .setHeader("CamelThymeleafResourceUri").constant("path/to/my/template.txt")
+  .setHeader("CamelThymeleafResourceUri").constant("path/to/my/template.html")
   .to("thymeleaf:dummy?allowTemplateFromHeader=true"");
 ---------------------------------------------------------------------------
 
@@ -203,15 +203,15 @@ from("direct:in")
 In this sample we want to use Thymeleaf templating for an order
 confirmation email. The email template is laid out in Thymeleaf as:
 
-.letter.txt
+.letter.html
 [source,text]
 ----------------------------------------------
-Dear ${headers.lastName}, ${headers.firstName}
+Dear [(${headers.lastName})], [(${headers.firstName})]
 
-Thanks for the order of ${headers.item}.
+Thanks for the order of [(${headers.item})].
 
 Regards Camel Riders Bookstore
-${body}
+[(${body})]
 ----------------------------------------------
 
 And the java code (from an unit test):
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafAbstractBaseTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafAbstractBaseTest.java
index f80064448a9..525a949a8a7 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafAbstractBaseTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafAbstractBaseTest.java
@@ -16,14 +16,14 @@
  */
 package org.apache.camel.component.thymeleaf;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.test.junit5.CamelTestSupport;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import static java.util.Map.entry;
 
 public abstract class ThymeleafAbstractBaseTest extends CamelTestSupport {
@@ -147,12 +147,12 @@ public abstract class ThymeleafAbstractBaseTest extends CamelTestSupport {
     protected String expected() {
 
         return "\n\n" +
-                "Dear Doe, Jane\n" +
-                "\n" +
-                "Thank you for your order number 7 of Widgets for Dummies.\n" +
-                "\n" +
-                "Regards Camel Riders Bookstore\n" +
-                "Spazz Testing Service";
+               "Dear Doe, Jane\n" +
+               "\n" +
+               "Thank you for your order number 7 of Widgets for Dummies.\n" +
+               "\n" +
+               "Regards Camel Riders Bookstore\n" +
+               "Spazz Testing Service";
     }
 
     @Override
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafBodyAsDomainObjectTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafBodyAsDomainObjectTest.java
index b7d6447382b..8dfac7e68b3 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafBodyAsDomainObjectTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafBodyAsDomainObjectTest.java
@@ -121,11 +121,11 @@ public class ThymeleafBodyAsDomainObjectTest extends ThymeleafAbstractBaseTest {
         public String toString() {
 
             return "Letter{" +
-                    "firstName='" + firstName + '\'' +
-                    ", lastName='" + lastName + '\'' +
-                    ", item='" + item + '\'' +
-                    ", closing='" + closing + '\'' +
-                    '}';
+                   "firstName='" + firstName + '\'' +
+                   ", lastName='" + lastName + '\'' +
+                   ", item='" + item + '\'' +
+                   ", closing='" + closing + '\'' +
+                   '}';
         }
 
     }
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafComponentTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafComponentTest.java
index e2578b165a6..efdb1b993b1 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafComponentTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafComponentTest.java
@@ -16,6 +16,10 @@
  */
 package org.apache.camel.component.thymeleaf;
 
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
 import org.apache.camel.support.PropertyBindingListener;
 import org.apache.camel.test.junit5.CamelTestSupport;
 import org.junit.jupiter.api.Test;
@@ -23,10 +27,6 @@ import org.thymeleaf.templatemode.TemplateMode;
 import org.thymeleaf.templateresolver.ITemplateResolver;
 import org.thymeleaf.templateresolver.StringTemplateResolver;
 
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-
 import static java.util.Map.entry;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafConcurrentTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafConcurrentTest.java
index 220939065d3..d38f6796379 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafConcurrentTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafConcurrentTest.java
@@ -16,13 +16,13 @@
  */
 package org.apache.camel.component.thymeleaf;
 
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.junit.jupiter.api.Test;
 
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
 import static org.apache.camel.test.junit5.TestSupport.body;
 
 public class ThymeleafConcurrentTest extends ThymeleafAbstractBaseTest {
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafContentCacheTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafContentCacheTest.java
index 42039d7194c..6469b06d2d9 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafContentCacheTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafContentCacheTest.java
@@ -16,6 +16,13 @@
  */
 package org.apache.camel.component.thymeleaf;
 
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
 import org.apache.camel.Exchange;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
@@ -23,12 +30,6 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.TestInstance;
 
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
 import static java.util.Map.entry;
 
 @TestInstance(TestInstance.Lifecycle.PER_METHOD)
@@ -200,8 +201,6 @@ public class ThymeleafContentCacheTest extends ThymeleafAbstractBaseTest {
 
             public void configure() {
 
-                context.setTracing(true);
-
                 from(DIRECT_START_NO_CACHE)
                         .setProperty(ORDER_NUMBER, simple("7"))
                         .to("thymeleaf://org/apache/camel/component/thymeleaf/letter-cached.html?cacheable=false&allowContextMapAll=true")
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafFileResolverAllParamsTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafFileResolverAllParamsTest.java
index 612c84bd962..7b38c49c34b 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafFileResolverAllParamsTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafFileResolverAllParamsTest.java
@@ -89,7 +89,6 @@ public class ThymeleafFileResolverAllParamsTest extends ThymeleafAbstractBaseTes
 
             public void configure() {
 
-                context.setTracing(true);
                 from(DIRECT_START)
                         .setBody(simple(SPAZZ_TESTING_SERVICE))
                         .to("thymeleaf:org/apache/camel/component/thymeleaf/letter?allowContextMapAll=true&cacheTimeToLive=500&cacheable=false&checkExistence=true&encoding=UTF-8&order=1&prefix=src/test/resources/&templateMode=HTML&resolver=FILE&suffix=.html")
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverAllParamsTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverAllParamsTest.java
index 2c35934fc66..9be2eeb6179 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverAllParamsTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverAllParamsTest.java
@@ -16,7 +16,12 @@
  */
 package org.apache.camel.component.thymeleaf;
 
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+
 import jakarta.servlet.ServletContext;
+
 import org.apache.camel.ExchangePattern;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
@@ -29,10 +34,6 @@ import org.thymeleaf.templateresolver.ITemplateResolver;
 import org.thymeleaf.templateresolver.WebApplicationTemplateResolver;
 import org.thymeleaf.web.servlet.JakartaServletWebApplication;
 
-import java.io.File;
-import java.io.InputStream;
-import java.net.URL;
-
 import static org.junit.jupiter.api.Assertions.assertAll;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
diff --git a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverTest.java b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverTest.java
index d75768e8aa0..e16270a2962 100644
--- a/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverTest.java
+++ b/components/camel-thymeleaf/src/test/java/org/apache/camel/component/thymeleaf/ThymeleafWebApplicationResolverTest.java
@@ -16,7 +16,11 @@
  */
 package org.apache.camel.component.thymeleaf;
 
+import java.io.File;
+import java.io.InputStream;
+
 import jakarta.servlet.ServletContext;
+
 import org.apache.camel.ExchangePattern;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
@@ -29,9 +33,6 @@ import org.thymeleaf.templateresolver.ITemplateResolver;
 import org.thymeleaf.templateresolver.WebApplicationTemplateResolver;
 import org.thymeleaf.web.servlet.JakartaServletWebApplication;
 
-import java.io.File;
-import java.io.InputStream;
-
 import static org.junit.jupiter.api.Assertions.assertAll;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
diff --git a/components/camel-thymeleaf/src/test/resources/log4j2.properties b/components/camel-thymeleaf/src/test/resources/log4j2.properties
index 4aafcbf3eed..3ee03fc4552 100644
--- a/components/camel-thymeleaf/src/test/resources/log4j2.properties
+++ b/components/camel-thymeleaf/src/test/resources/log4j2.properties
@@ -30,7 +30,7 @@ rootLogger.appenderRef.stdout.ref = stdout
 #logger.thymeleaf.name = org.apache.camel.component.thymeleaf
 #logger.thymeleaf.level = INFO
 logger.camel.name = org.apache.camel
-logger.camel.level = DEBUG
+logger.camel.level = INFO
 logger.springframework.name = org.springframework
 logger.springframework.level = INFO
 


[camel] 10/10: Camel-Thymeleaf: Log for tests only on file

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit c64da1bec3bd0dd0124e7deaf21c011d2d070286
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Tue Sep 12 08:23:24 2023 +0200

    Camel-Thymeleaf: Log for tests only on file
    
    Signed-off-by: Andrea Cosentino <an...@gmail.com>
---
 .../src/test/resources/log4j2.properties            | 21 +++++++--------------
 1 file changed, 7 insertions(+), 14 deletions(-)

diff --git a/components/camel-thymeleaf/src/test/resources/log4j2.properties b/components/camel-thymeleaf/src/test/resources/log4j2.properties
index 3ee03fc4552..71bdf57528e 100644
--- a/components/camel-thymeleaf/src/test/resources/log4j2.properties
+++ b/components/camel-thymeleaf/src/test/resources/log4j2.properties
@@ -15,22 +15,15 @@
 ## limitations under the License.
 ## ---------------------------------------------------------------------------
 
-appender.out.type = File
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-thymeleaf-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.fileName = target/camel-thymeleaf-test.log
 appender.out.layout.type = PatternLayout
 appender.out.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
-appender.stdout.type = Console
-appender.stdout.name = stdout
-appender.stdout.layout.type = PatternLayout
-appender.stdout.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
 rootLogger.level = INFO
-rootLogger.appenderRef.out.ref = out
-rootLogger.appenderRef.stdout.ref = stdout
-#logger.thymeleaf.name = org.apache.camel.component.thymeleaf
-#logger.thymeleaf.level = INFO
-logger.camel.name = org.apache.camel
-logger.camel.level = INFO
-logger.springframework.name = org.springframework
-logger.springframework.level = INFO
+rootLogger.appenderRef.file.ref = file