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

[camel] 01/02: CAMEL-19411: camel-kamelet - Kamelets should be as its a single component, and not a route with its own error handling. Therefore we turn off error handling in the template to make it work better with user configured error handling. Added option to be backwards compatible

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

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

commit 9eb61bb9f62bb1e00def3671f053fdab1db09b43
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Jun 13 13:16:18 2023 +0200

    CAMEL-19411: camel-kamelet - Kamelets should be as its a single component, and not a route with its own error handling. Therefore we turn off error handling in the template to make it work better with user configured error handling. Added option to be backwards compatible
---
 .../kamelet/KameletComponentConfigurer.java        |  6 +++
 .../kamelet/KameletEndpointConfigurer.java         |  6 +++
 .../kamelet/KameletEndpointUriFactory.java         |  3 +-
 .../apache/camel/component/kamelet/kamelet.json    |  6 ++-
 .../apache/camel/component/kamelet/Kamelet.java    |  6 +++
 .../camel/component/kamelet/KameletComponent.java  | 18 +++++++
 .../camel/component/kamelet/KameletEndpoint.java   | 14 +++++
 .../component/kamelet/KameletHttpSinkTest.java     | 54 ++++++++++++++++++++
 .../kamelet/KameletNoErrorHandlerDirectTest.java   | 59 ++++++++++++++++++++++
 ...ameletNoErrorHandlerRouteConfigurationTest.java | 57 +++++++++++++++++++++
 .../kamelet/KameletNoErrorHandlerTest.java         | 53 +++++++++++++++++++
 11 files changed, 279 insertions(+), 3 deletions(-)

diff --git a/components/camel-kamelet/src/generated/java/org/apache/camel/component/kamelet/KameletComponentConfigurer.java b/components/camel-kamelet/src/generated/java/org/apache/camel/component/kamelet/KameletComponentConfigurer.java
index f734ad0062e..0b065a9c7bb 100644
--- a/components/camel-kamelet/src/generated/java/org/apache/camel/component/kamelet/KameletComponentConfigurer.java
+++ b/components/camel-kamelet/src/generated/java/org/apache/camel/component/kamelet/KameletComponentConfigurer.java
@@ -29,6 +29,8 @@ public class KameletComponentConfigurer extends PropertyConfigurerSupport implem
         case "lazystartproducer":
         case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
         case "location": target.setLocation(property(camelContext, java.lang.String.class, value)); return true;
+        case "noerrorhandler":
+        case "noErrorHandler": target.setNoErrorHandler(property(camelContext, boolean.class, value)); return true;
         case "routeproperties":
         case "routeProperties": target.setRouteProperties(property(camelContext, java.util.Map.class, value)); return true;
         case "routetemplateloaderlistener":
@@ -56,6 +58,8 @@ public class KameletComponentConfigurer extends PropertyConfigurerSupport implem
         case "lazystartproducer":
         case "lazyStartProducer": return boolean.class;
         case "location": return java.lang.String.class;
+        case "noerrorhandler":
+        case "noErrorHandler": return boolean.class;
         case "routeproperties":
         case "routeProperties": return java.util.Map.class;
         case "routetemplateloaderlistener":
@@ -79,6 +83,8 @@ public class KameletComponentConfigurer extends PropertyConfigurerSupport implem
         case "lazystartproducer":
         case "lazyStartProducer": return target.isLazyStartProducer();
         case "location": return target.getLocation();
+        case "noerrorhandler":
+        case "noErrorHandler": return target.isNoErrorHandler();
         case "routeproperties":
         case "routeProperties": return target.getRouteProperties();
         case "routetemplateloaderlistener":
diff --git a/components/camel-kamelet/src/generated/java/org/apache/camel/component/kamelet/KameletEndpointConfigurer.java b/components/camel-kamelet/src/generated/java/org/apache/camel/component/kamelet/KameletEndpointConfigurer.java
index 9883db35a2e..18dced3a51a 100644
--- a/components/camel-kamelet/src/generated/java/org/apache/camel/component/kamelet/KameletEndpointConfigurer.java
+++ b/components/camel-kamelet/src/generated/java/org/apache/camel/component/kamelet/KameletEndpointConfigurer.java
@@ -33,6 +33,8 @@ public class KameletEndpointConfigurer extends PropertyConfigurerSupport impleme
         case "lazystartproducer":
         case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
         case "location": target.setLocation(property(camelContext, java.lang.String.class, value)); return true;
+        case "noerrorhandler":
+        case "noErrorHandler": target.setNoErrorHandler(property(camelContext, boolean.class, value)); return true;
         case "timeout": target.setTimeout(property(camelContext, long.class, value)); return true;
         default: return false;
         }
@@ -53,6 +55,8 @@ public class KameletEndpointConfigurer extends PropertyConfigurerSupport impleme
         case "lazystartproducer":
         case "lazyStartProducer": return boolean.class;
         case "location": return java.lang.String.class;
+        case "noerrorhandler":
+        case "noErrorHandler": return boolean.class;
         case "timeout": return long.class;
         default: return null;
         }
@@ -74,6 +78,8 @@ public class KameletEndpointConfigurer extends PropertyConfigurerSupport impleme
         case "lazystartproducer":
         case "lazyStartProducer": return target.isLazyStartProducer();
         case "location": return target.getLocation();
+        case "noerrorhandler":
+        case "noErrorHandler": return target.isNoErrorHandler();
         case "timeout": return target.getTimeout();
         default: return null;
         }
diff --git a/components/camel-kamelet/src/generated/java/org/apache/camel/component/kamelet/KameletEndpointUriFactory.java b/components/camel-kamelet/src/generated/java/org/apache/camel/component/kamelet/KameletEndpointUriFactory.java
index 969003ddf10..8744b1c6321 100644
--- a/components/camel-kamelet/src/generated/java/org/apache/camel/component/kamelet/KameletEndpointUriFactory.java
+++ b/components/camel-kamelet/src/generated/java/org/apache/camel/component/kamelet/KameletEndpointUriFactory.java
@@ -21,7 +21,7 @@ public class KameletEndpointUriFactory extends org.apache.camel.support.componen
     private static final Set<String> SECRET_PROPERTY_NAMES;
     private static final Set<String> MULTI_VALUE_PREFIXES;
     static {
-        Set<String> props = new HashSet<>(10);
+        Set<String> props = new HashSet<>(11);
         props.add("block");
         props.add("bridgeErrorHandler");
         props.add("exceptionHandler");
@@ -29,6 +29,7 @@ public class KameletEndpointUriFactory extends org.apache.camel.support.componen
         props.add("failIfNoConsumers");
         props.add("lazyStartProducer");
         props.add("location");
+        props.add("noErrorHandler");
         props.add("routeId");
         props.add("templateId");
         props.add("timeout");
diff --git a/components/camel-kamelet/src/generated/resources/org/apache/camel/component/kamelet/kamelet.json b/components/camel-kamelet/src/generated/resources/org/apache/camel/component/kamelet/kamelet.json
index 9431fd0616c..3cedf825851 100644
--- a/components/camel-kamelet/src/generated/resources/org/apache/camel/component/kamelet/kamelet.json
+++ b/components/camel-kamelet/src/generated/resources/org/apache/camel/component/kamelet/kamelet.json
@@ -30,7 +30,8 @@
     "lazyStartProducer": { "index": 5, "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 [...]
     "timeout": { "index": 6, "kind": "property", "displayName": "Timeout", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "description": "The timeout value to use if block is enabled." },
     "autowiredEnabled": { "index": 7, "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 [...]
-    "routeTemplateLoaderListener": { "index": 8, "kind": "property", "displayName": "Route Template Loader Listener", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.RouteTemplateLoaderListener", "deprecated": false, "autowired": true, "secret": false, "description": "To plugin a custom listener for when the Kamelet component is loading Kamelets from external resources." }
+    "noErrorHandler": { "index": 8, "kind": "property", "displayName": "No Error Handler", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Kamelets, by default, will not do fine-grained error handling, but works in no-error-handler mode. This can be turned off, to use old behaviour in earlier versions of Camel." },
+    "routeTemplateLoaderListener": { "index": 9, "kind": "property", "displayName": "Route Template Loader Listener", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.RouteTemplateLoaderListener", "deprecated": false, "autowired": true, "secret": false, "description": "To plugin a custom listener for when the Kamelet component is loading Kamelets from external resources." }
   },
   "properties": {
     "templateId": { "index": 0, "kind": "path", "displayName": "Template Id", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Route Template ID" },
@@ -42,6 +43,7 @@
     "failIfNoConsumers": { "index": 6, "kind": "parameter", "displayName": "Fail If No Consumers", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the producer should fail by throwing an exception, when sending to a kamelet endpoint with no active consumers." },
     "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 [...]
     "timeout": { "index": 8, "kind": "parameter", "displayName": "Timeout", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "description": "The timeout value to use if block is enabled." },
-    "location": { "index": 9, "kind": "parameter", "displayName": "Location", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Location of the Kamelet to use which can be specified as a resource from file system, classpath etc. The location cannot use wildcards, and must refer to a file including extension, for example file:\/etc\/ [...]
+    "location": { "index": 9, "kind": "parameter", "displayName": "Location", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Location of the Kamelet to use which can be specified as a resource from file system, classpath etc. The location cannot use wildcards, and must refer to a file including extension, for example file:\/etc\/ [...]
+    "noErrorHandler": { "index": 10, "kind": "parameter", "displayName": "No Error Handler", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Kamelets, by default, will not do fine-grained error handling, but works in no-error-handler mode. This can be turned off, to use old behaviour in earlier versions of Camel." }
   }
 }
diff --git a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/Kamelet.java b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/Kamelet.java
index d538f73cf9c..bda62f27103 100644
--- a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/Kamelet.java
+++ b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/Kamelet.java
@@ -22,6 +22,7 @@ import java.util.Properties;
 import java.util.function.Predicate;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.builder.NoErrorHandlerBuilder;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.RouteTemplateDefinition;
 import org.apache.camel.model.ToDefinition;
@@ -43,6 +44,7 @@ public final class Kamelet {
     public static final String PARAM_TEMPLATE_ID = "templateId";
     public static final String PARAM_LOCATION = "location";
     public static final String DEFAULT_LOCATION = "classpath:/kamelets";
+    public static final String NO_ERROR_HANDLER = "noErrorHandler";
 
     // use a running counter as uuid
     private static final UuidGenerator UUID = new SimpleUuidGenerator();
@@ -123,6 +125,7 @@ public final class Kamelet {
 
     public static RouteDefinition templateToRoute(RouteTemplateDefinition in, Map<String, Object> parameters) {
         final String rid = (String) parameters.get(PARAM_ROUTE_ID);
+        final boolean noErrorHandler = (boolean) parameters.get(NO_ERROR_HANDLER);
 
         ObjectHelper.notNull(rid, PARAM_ROUTE_ID);
 
@@ -130,6 +133,9 @@ public final class Kamelet {
         def.setLocation(in.getLocation());
         def.setLineNumber(in.getLineNumber());
         def.setId(rid);
+        if (noErrorHandler) {
+            def.setErrorHandlerFactory(new NoErrorHandlerBuilder());
+        }
 
         if (def.getInput() == null) {
             throw new IllegalArgumentException("Camel route " + rid + " input does not exist.");
diff --git a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletComponent.java b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletComponent.java
index b54205a8ed0..eede00621b4 100644
--- a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletComponent.java
+++ b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletComponent.java
@@ -45,6 +45,7 @@ import org.apache.camel.util.URISupport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.camel.component.kamelet.Kamelet.NO_ERROR_HANDLER;
 import static org.apache.camel.component.kamelet.Kamelet.PARAM_LOCATION;
 import static org.apache.camel.component.kamelet.Kamelet.PARAM_ROUTE_ID;
 import static org.apache.camel.component.kamelet.Kamelet.PARAM_TEMPLATE_ID;
@@ -76,6 +77,8 @@ public class KameletComponent extends DefaultComponent {
     private boolean block = true;
     @Metadata(label = "producer", defaultValue = "30000")
     private long timeout = 30000L;
+    @Metadata(label = "advanced", defaultValue = "true")
+    private boolean noErrorHandler = true;
 
     @Metadata
     private Map<String, Properties> templateProperties;
@@ -141,6 +144,7 @@ public class KameletComponent extends DefaultComponent {
             endpoint = new KameletEndpoint(uri, this, templateId, routeId);
 
             // forward component properties
+            endpoint.setNoErrorHandler(noErrorHandler);
             endpoint.setBlock(block);
             endpoint.setTimeout(timeout);
             // endpoint specific location
@@ -162,6 +166,7 @@ public class KameletComponent extends DefaultComponent {
             };
 
             // forward component properties
+            endpoint.setNoErrorHandler(noErrorHandler);
             endpoint.setBlock(block);
             endpoint.setTimeout(timeout);
             // endpoint specific location
@@ -219,6 +224,7 @@ public class KameletComponent extends DefaultComponent {
             //
             kameletProperties.put(PARAM_TEMPLATE_ID, templateId);
             kameletProperties.put(PARAM_ROUTE_ID, routeId);
+            kameletProperties.put(NO_ERROR_HANDLER, endpoint.isNoErrorHandler());
 
             // set kamelet specific properties
             endpoint.setKameletProperties(kameletProperties);
@@ -240,6 +246,18 @@ public class KameletComponent extends DefaultComponent {
         return false;
     }
 
+    public boolean isNoErrorHandler() {
+        return noErrorHandler;
+    }
+
+    /**
+     * Kamelets, by default, will not do fine-grained error handling, but works in no-error-handler mode. This can be
+     * turned off, to use old behaviour in earlier versions of Camel.
+     */
+    public void setNoErrorHandler(boolean noErrorHandler) {
+        this.noErrorHandler = noErrorHandler;
+    }
+
     public boolean isBlock() {
         return block;
     }
diff --git a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletEndpoint.java b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletEndpoint.java
index af79b4cbc1d..0ba9c80057d 100644
--- a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletEndpoint.java
+++ b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletEndpoint.java
@@ -56,6 +56,8 @@ public class KameletEndpoint extends DefaultEndpoint {
     private long timeout = 30000L;
     @UriParam(label = "producer,advanced", defaultValue = "true")
     private boolean failIfNoConsumers = true;
+    @UriParam(label = "advanced", defaultValue = "true")
+    private boolean noErrorHandler = true;
 
     public KameletEndpoint(String uri,
                            KameletComponent component,
@@ -73,6 +75,18 @@ public class KameletEndpoint extends DefaultEndpoint {
         this.kameletProperties = new HashMap<>();
     }
 
+    public boolean isNoErrorHandler() {
+        return noErrorHandler;
+    }
+
+    /**
+     * Kamelets, by default, will not do fine-grained error handling, but works in no-error-handler mode. This can be
+     * turned off, to use old behaviour in earlier versions of Camel.
+     */
+    public void setNoErrorHandler(boolean noErrorHandler) {
+        this.noErrorHandler = noErrorHandler;
+    }
+
     public boolean isBlock() {
         return block;
     }
diff --git a/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletHttpSinkTest.java b/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletHttpSinkTest.java
new file mode 100644
index 00000000000..afded2f1787
--- /dev/null
+++ b/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletHttpSinkTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.kamelet;
+
+import org.apache.camel.RoutesBuilder;
+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 KameletHttpSinkTest extends CamelTestSupport {
+
+    @Test
+    public void testHttpSink() throws Exception {
+        getMockEndpoint("mock:dead").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Hello World");
+
+        MockEndpoint.assertIsSatisfied(context);
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                routeTemplate("myhttp")
+                        .templateParameter("url")
+                        .from("kamelet:source")
+                        .removeHeaders("*")
+                        .to("{{url}}");
+
+                from("direct:start").routeId("test")
+                        .errorHandler(deadLetterChannel("mock:dead"))
+                        .kamelet("myhttp?url=https://webhook.unknownhost.sitessss/")
+                        .log("${body}");
+            }
+        };
+    }
+}
diff --git a/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletNoErrorHandlerDirectTest.java b/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletNoErrorHandlerDirectTest.java
new file mode 100644
index 00000000000..371f1140308
--- /dev/null
+++ b/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletNoErrorHandlerDirectTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.kamelet;
+
+import org.apache.camel.RoutesBuilder;
+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 KameletNoErrorHandlerDirectTest extends CamelTestSupport {
+
+    @Test
+    public void testNoErrorHandler() throws Exception {
+        getMockEndpoint("mock:catch").expectedMessageCount(1);
+        getMockEndpoint("mock:dead").expectedMessageCount(0);
+
+        template.sendBody("direct:start", "Hello World");
+
+        MockEndpoint.assertIsSatisfied(context);
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                routeTemplate("echo")
+                        .templateParameter("prefix")
+                        .from("kamelet:source")
+                        .throwException(new IllegalArgumentException("Forced"));
+
+                errorHandler(deadLetterChannel("mock:dead"));
+
+                from("direct:start").routeId("test")
+                        .doTry()
+                            .to("kamelet:echo?prefix=a")
+                        .doCatch(Exception.class)
+                            .to("mock:catch")
+                        .end()
+                        .log("${body}");
+            }
+        };
+    }
+}
diff --git a/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletNoErrorHandlerRouteConfigurationTest.java b/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletNoErrorHandlerRouteConfigurationTest.java
new file mode 100644
index 00000000000..5bc4891e8cf
--- /dev/null
+++ b/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletNoErrorHandlerRouteConfigurationTest.java
@@ -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.
+ */
+package org.apache.camel.component.kamelet;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteConfigurationBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+public class KameletNoErrorHandlerRouteConfigurationTest extends CamelTestSupport {
+
+    @Test
+    public void testNoErrorHandler() throws Exception {
+        getMockEndpoint("mock:dead").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Hello World");
+
+        MockEndpoint.assertIsSatisfied(context);
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() {
+        return new RouteConfigurationBuilder() {
+            @Override
+            public void configure() {
+                routeTemplate("echo")
+                        .templateParameter("prefix")
+                        .from("kamelet:source")
+                        .throwException(new IllegalArgumentException("Forced"));
+
+                from("direct:start").routeId("test")
+                        .to("kamelet:echo?prefix=a")
+                        .log("${body}");
+            }
+
+            @Override
+            public void configuration() throws Exception {
+                errorHandler(deadLetterChannel("mock:dead"));
+            }
+        };
+    }
+}
diff --git a/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletNoErrorHandlerTest.java b/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletNoErrorHandlerTest.java
new file mode 100644
index 00000000000..ba78c36d58a
--- /dev/null
+++ b/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletNoErrorHandlerTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.kamelet;
+
+import org.apache.camel.RoutesBuilder;
+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 KameletNoErrorHandlerTest extends CamelTestSupport {
+
+    @Test
+    public void testNoErrorHandler() throws Exception {
+        getMockEndpoint("mock:dead").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Hello World");
+
+        MockEndpoint.assertIsSatisfied(context);
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                routeTemplate("echo")
+                        .templateParameter("prefix")
+                        .from("kamelet:source")
+                        .throwException(new IllegalArgumentException("Forced"));
+
+                from("direct:start").routeId("test")
+                        .errorHandler(deadLetterChannel("mock:dead"))
+                        .to("kamelet:echo?prefix=a")
+                        .log("${body}");
+            }
+        };
+    }
+}