This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 43f90a5902d CAMEL-21599: camel-kamelet - Use error handler from
calling route so end users are in full control and its more natural (#16935)
43f90a5902d is described below
commit 43f90a5902d551ced4d77ca36183d8efbabe1fdd
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Jan 27 11:58:25 2025 +0100
CAMEL-21599: camel-kamelet - Use error handler from calling route so end
users are in full control and its more natural (#16935)
* CAMEL-21599: camel-kamelet - Rework error handler for kamelets to be more
standard Camel.
---
.../apache/camel/catalog/components/kamelet.json | 4 +-
.../apache/camel/component/kamelet/kamelet.json | 4 +-
.../src/main/docs/kamelet-component.adoc | 52 ++++++++-
.../apache/camel/component/kamelet/Kamelet.java | 25 ++++
.../camel/component/kamelet/KameletComponent.java | 41 ++++---
.../camel/component/kamelet/KameletEndpoint.java | 13 ++-
.../camel/component/kamelet/KameletProcessor.java | 23 +---
.../camel/component/kamelet/KameletProducer.java | 1 +
.../camel/component/kamelet/KameletReifier.java | 15 ++-
.../kamelet/KameletNoErrorHandlerTest.java | 6 +-
...andlerTest.java => KameletRouteSingleTest.java} | 26 +++--
....java => KameletSinkDeadLetterChannelTest.java} | 35 +++---
...ava => KameletSourceDeadLetterChannelTest.java} | 21 ++--
...lerDirectTest.java => KameletTryCatchTest.java} | 4 +-
.../main/java/org/apache/camel/CamelContext.java | 18 +++
.../org/apache/camel/ExtendedCamelContext.java | 37 ++++++
.../impl/engine/DefaultCamelContextExtension.java | 30 +++++
.../camel/impl/engine/InternalServiceManager.java | 14 +--
.../camel/impl/engine/SimpleCamelContext.java | 8 ++
.../org/apache/camel/impl/DefaultCamelContext.java | 26 +++--
.../java/org/apache/camel/impl/DefaultModel.java | 26 +++++
.../main/java/org/apache/camel/model/Model.java | 18 +++
.../camel/model/ProcessorDefinitionHelper.java | 55 +++++++++
.../org/apache/camel/reifier/ProcessorReifier.java | 126 ++++++++-------------
.../ROOT/pages/camel-4x-upgrade-guide-4_10.adoc | 66 +++++++++++
.../dsl/KameletComponentBuilderFactory.java | 13 ++-
.../dsl/KameletEndpointBuilderFactory.java | 78 +++++++++----
27 files changed, 569 insertions(+), 216 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kamelet.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kamelet.json
index 377a4908ac5..1d696ba4356 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kamelet.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kamelet.json
@@ -32,7 +32,7 @@
"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 [...]
- "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." },
+ "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": false, "description": "Whether kamelets
should use error handling or not. By default, the Kamelet uses the same error
handler as from the calling route. This means that if the calling route has
error handling that performs r [...]
"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": {
@@ -46,6 +46,6 @@
"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\/ [...]
- "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." }
+ "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": false, "description": "Whether kamelets
should use error handling or not. By default, the Kamelet uses the same error
handler as from the calling route. This means that if the calling route has
error handling that performs [...]
}
}
diff --git
a/components/camel-kamelet/src/generated/resources/META-INF/org/apache/camel/component/kamelet/kamelet.json
b/components/camel-kamelet/src/generated/resources/META-INF/org/apache/camel/component/kamelet/kamelet.json
index 377a4908ac5..1d696ba4356 100644
---
a/components/camel-kamelet/src/generated/resources/META-INF/org/apache/camel/component/kamelet/kamelet.json
+++
b/components/camel-kamelet/src/generated/resources/META-INF/org/apache/camel/component/kamelet/kamelet.json
@@ -32,7 +32,7 @@
"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 [...]
- "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." },
+ "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": false, "description": "Whether kamelets
should use error handling or not. By default, the Kamelet uses the same error
handler as from the calling route. This means that if the calling route has
error handling that performs r [...]
"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": {
@@ -46,6 +46,6 @@
"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\/ [...]
- "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." }
+ "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": false, "description": "Whether kamelets
should use error handling or not. By default, the Kamelet uses the same error
handler as from the calling route. This means that if the calling route has
error handling that performs [...]
}
}
diff --git a/components/camel-kamelet/src/main/docs/kamelet-component.adoc
b/components/camel-kamelet/src/main/docs/kamelet-component.adoc
index acff0f237f0..f00bde4d287 100644
--- a/components/camel-kamelet/src/main/docs/kamelet-component.adoc
+++ b/components/camel-kamelet/src/main/docs/kamelet-component.adoc
@@ -48,8 +48,56 @@ The *kamelet* endpoint is *lenient*, which means that the
endpoint accepts addit
If a xref:manual::route-template.adoc[Route Template] is not found, the
*kamelet* endpoint tries to load the related *kamelet* definition from the file
system (by default `classpath:kamelets`). The default resolution mechanism
expects _Kamelets_ files to have the extension `.kamelet.yaml`.
-== Examples
+=== Error Handling
+
+The error handling when using kamelets are using the same error handling
+that are from the route where the kamelets are being used.
+
+Suppose you have kamelets that would cause an exception during processing, such
+as the source below. Now because the route has been configured with a _dead
letter channel_
+as the error handler, then the exception from the kamelet will be handled by
the route error handler.
+Which means you will se a WARN being logged.
+
+[source,yaml]
+----
+- route:
+ errorHandler:
+ deadLetterChannel:
+ deadLetterUri: log:dead?level=WARN
+ id: myRoute
+ from:
+ uri: "kamelet:my-error-source/source"
+ steps:
+ - log: "${body}"
+----
+For sink kamelets then error handling also allows to perform retries.
+
+So suppose you have the following route:
+
+[source,yaml]
+----
+- route:
+ errorHandler:
+ deadLetterChannel:
+ deadLetterUri: log:dead?level=WARN
+ redeliveryPolicy:
+ maximumRedeliveries: 5
+ redeliveryDelay: "5000"
+ id: myRoute
+ from:
+ uri: "direct:start"
+ steps:
+ - to:
+ uri: "kamelet:my-error-sink/sink"
+ - log: "${body}"
+----
+
+Then notice the error handler has been configured to do redeliveries up till 5
times with 5 sec delay between.
+Suppose the sink kamelet is throwing an exception, then Camel will now perform
the redelivery attempt
+at the point of origin, which means inside the Kamelet.
+
+== Examples
_Kamelets_ can be used as if they were standard Camel components.
For example, suppose that we have created a Route Template as follows:
@@ -100,6 +148,4 @@ from("direct:template")
----
-
-
include::spring-boot:partial$starter.adoc[]
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 da2cdc792b0..5e7c905ad4c 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
@@ -24,6 +24,9 @@ import java.util.function.Predicate;
import org.apache.camel.CamelContext;
import org.apache.camel.builder.NoErrorHandlerBuilder;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.model.ProcessorDefinitionHelper;
import org.apache.camel.model.RouteDefinition;
import org.apache.camel.model.RouteTemplateDefinition;
import org.apache.camel.model.ToDefinition;
@@ -48,6 +51,8 @@ public final class Kamelet {
public static final String PARAM_LOCATION = "location";
public static final String PARAM_UUID = "uuid";
public static final String DEFAULT_LOCATION = "classpath:kamelets";
+ public static final String PARENT_ROUTE_ID = "parentRouteId";
+ public static final String PARENT_PROCESSOR_ID = "parentProcessorId";
public static final String NO_ERROR_HANDLER = "noErrorHandler";
// use a running counter as uuid
@@ -182,6 +187,8 @@ public final class Kamelet {
final String rid = (String) parameters.get(PARAM_ROUTE_ID);
final boolean noErrorHandler = (boolean)
parameters.get(NO_ERROR_HANDLER);
final String uuid = (String) parameters.get(PARAM_UUID);
+ final String prid = (String) parameters.get(PARENT_ROUTE_ID);
+ final String ppid = (String) parameters.get(PARENT_PROCESSOR_ID);
ObjectHelper.notNull(rid, PARAM_ROUTE_ID);
ObjectHelper.notNull(uuid, PARAM_UUID);
@@ -195,6 +202,24 @@ public final class Kamelet {
def.setNodePrefixId(uuid);
if (noErrorHandler) {
def.setErrorHandlerFactory(new NoErrorHandlerBuilder());
+ } else if (prid != null) {
+ ModelCamelContext mcc = (ModelCamelContext) in.getCamelContext();
+ RouteDefinition parent = mcc.getRouteDefinition(prid);
+ boolean wrap = true;
+
+ // the kamelet are used from a processor, and we need to check if
this processor
+ // has any error handler or not (if not then we should also not
use error handler in the kamelet)
+ // (if ppid is null then it is a source kamelet)
+ if (ppid != null) {
+ ProcessorDefinition<?> pro = mcc.getProcessorDefinition(ppid);
+ wrap = pro == null ||
ProcessorDefinitionHelper.shouldWrapInErrorHandler(def.getCamelContext(), pro,
null,
+ pro.getInheritErrorHandler());
+ }
+ if (wrap && parent != null) {
+
def.setErrorHandlerFactory(parent.getErrorHandlerFactory().cloneBuilder());
+ } else {
+ def.setErrorHandlerFactory(new NoErrorHandlerBuilder());
+ }
}
if (def.getInput() == null) {
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 e7d493e0d1a..97711779607 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
@@ -85,8 +85,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(label = "advanced")
+ private boolean noErrorHandler;
@Metadata
private Map<String, Properties> templateProperties;
@@ -171,7 +171,9 @@ public class KameletComponent extends DefaultComponent {
// since this is the real kamelet, then we need to hand it
// over to the tracker.
//
- lifecycleHandler.track(this);
+ String routeId =
getCamelContext().getCamelContextExtension().getCreateRoute();
+ String processorId =
getCamelContext().getCamelContextExtension().getCreateProcessor();
+ lifecycleHandler.track(this, routeId, processorId);
}
};
@@ -271,8 +273,13 @@ public class KameletComponent extends DefaultComponent {
}
/**
- * 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.
+ * Whether kamelets should use error handling or not. By default, the
Kamelet uses the same error handler as from
+ * the calling route. This means that if the calling route has error
handling that performs retries, or routing to a
+ * dead letter channel, then the kamelet route will use this also.
+ * <p>
+ * This can be turned off by setting this option to true. If off then the
kamelet route is not using error handling,
+ * and any exception thrown will for source kamelets be logged by the
consumer, and the sink/action kamelets will
+ * fail processing.
*/
public void setNoErrorHandler(boolean noErrorHandler) {
this.noErrorHandler = noErrorHandler;
@@ -431,7 +438,11 @@ public class KameletComponent extends DefaultComponent {
* be used to create routes from templates.
*/
private class LifecycleHandler extends LifecycleStrategySupport {
- private final List<KameletEndpoint> endpoints;
+
+ record Tuple(KameletEndpoint endpoint, String parentRouteId, String
parentProcessorId) {
+ }
+
+ private final List<Tuple> endpoints;
private final AtomicBoolean initialized;
public LifecycleHandler() {
@@ -439,7 +450,8 @@ public class KameletComponent extends DefaultComponent {
this.initialized = new AtomicBoolean();
}
- public void createRouteForEndpoint(KameletEndpoint endpoint) throws
Exception {
+ public void createRouteForEndpoint(KameletEndpoint endpoint, String
parentRouteId, String parentProcessorId)
+ throws Exception {
final ModelCamelContext context = (ModelCamelContext)
getCamelContext();
final String templateId = endpoint.getTemplateId();
final String routeId = endpoint.getRouteId();
@@ -454,7 +466,8 @@ public class KameletComponent extends DefaultComponent {
LOG.debug("Creating route from template={} and id={}", templateId,
routeId);
try {
- String id = context.addRouteFromTemplate(routeId, templateId,
uuid, endpoint.getKameletProperties());
+ String id = context.addRouteFromKamelet(routeId, templateId,
uuid, parentRouteId, parentProcessorId,
+ endpoint.getKameletProperties());
RouteDefinition def = context.getRouteDefinition(id);
// start the route if not already started
@@ -473,12 +486,12 @@ public class KameletComponent extends DefaultComponent {
@Override
public void onContextInitialized(CamelContext context) throws
VetoCamelContextStartException {
if (this.initialized.compareAndSet(false, true)) {
- for (KameletEndpoint endpoint : endpoints) {
+ for (Tuple tuple : endpoints) {
try {
- createRouteForEndpoint(endpoint);
+ createRouteForEndpoint(tuple.endpoint,
tuple.parentRouteId, tuple.parentProcessorId);
} catch (Exception e) {
throw new VetoCamelContextStartException(
- "Failure creating route from template: " +
endpoint.getTemplateId(), e, context);
+ "Failure creating route from template: " +
tuple.endpoint.getTemplateId(), e, context);
}
}
@@ -490,16 +503,16 @@ public class KameletComponent extends DefaultComponent {
this.initialized.set(initialized);
}
- public void track(KameletEndpoint endpoint) {
+ public void track(KameletEndpoint endpoint, String parentRouteId,
String parentProcessorId) {
if (this.initialized.get()) {
try {
- createRouteForEndpoint(endpoint);
+ createRouteForEndpoint(endpoint, parentRouteId,
parentProcessorId);
} catch (Exception e) {
throw RuntimeCamelException.wrapRuntimeException(e);
}
} else {
LOG.debug("Tracking route template={} and id={}",
endpoint.getTemplateId(), endpoint.getRouteId());
- this.endpoints.add(endpoint);
+ this.endpoints.add(new Tuple(endpoint, parentRouteId,
parentProcessorId));
}
}
}
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 0ba9c80057d..8481f3eeaa1 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,8 +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;
+ @UriParam(label = "advanced")
+ private boolean noErrorHandler;
public KameletEndpoint(String uri,
KameletComponent component,
@@ -80,8 +80,13 @@ public class KameletEndpoint extends DefaultEndpoint {
}
/**
- * 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.
+ * Whether kamelets should use error handling or not. By default, the
Kamelet uses the same error handler as from
+ * the calling route. This means that if the calling route has error
handling that performs retries, or routing to a
+ * dead letter channel, then the kamelet route will use this also.
+ * <p>
+ * This can be turned off by setting this option to true. If off then the
kamelet route is not using error handling,
+ * and any exception thrown will for source kamelets be logged by the
consumer, and the sink/action kamelets will
+ * fail processing.
*/
public void setNoErrorHandler(boolean noErrorHandler) {
this.noErrorHandler = noErrorHandler;
diff --git
a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletProcessor.java
b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletProcessor.java
index 9bfab346d8f..2417aedbd81 100644
---
a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletProcessor.java
+++
b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletProcessor.java
@@ -49,7 +49,7 @@ public class KameletProcessor extends AsyncProcessorSupport
private String id;
private String routeId;
- public KameletProcessor(CamelContext camelContext, String name, Processor
processor) {
+ public KameletProcessor(CamelContext camelContext, String name, Processor
processor) throws Exception {
this.camelContext = camelContext;
this.name = name;
this.processor = AsyncProcessorConverterHelper.convert(processor);
@@ -116,17 +116,11 @@ public class KameletProcessor extends
AsyncProcessorSupport
}
@Override
- protected void doBuild() throws Exception {
- if (component == null) {
- component = camelContext.getComponent("kamelet",
KameletComponent.class);
- }
- if (producer == null) {
- producer = (KameletProducer) camelContext.getEndpoint("kamelet://"
+ name).createAsyncProducer();
- }
- if (producer != null) {
- ((RouteIdAware) producer).setRouteId(getRouteId());
- }
- ServiceHelper.buildService(processor, producer);
+ protected void doInit() throws Exception {
+ this.component = camelContext.getComponent("kamelet",
KameletComponent.class);
+ this.producer = (KameletProducer)
camelContext.getEndpoint("kamelet://" + name).createAsyncProducer();
+
+ ServiceHelper.initService(processor, producer);
// we use the kamelet component (producer) to call the kamelet
// and to receive the reply we register ourselves to the kamelet
component
@@ -134,11 +128,6 @@ public class KameletProcessor extends AsyncProcessorSupport
component.addKameletEip(producer.getKey(), processor);
}
- @Override
- protected void doInit() throws Exception {
- ServiceHelper.initService(processor, producer);
- }
-
@Override
protected void doStart() throws Exception {
ServiceHelper.startService(processor, producer);
diff --git
a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletProducer.java
b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletProducer.java
index 38d291a8fcd..1d219d524d3 100644
---
a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletProducer.java
+++
b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletProducer.java
@@ -141,6 +141,7 @@ final class KameletProducer extends DefaultAsyncProducer
implements RouteIdAware
@Override
protected void doInit() throws Exception {
+ super.doInit();
ManagementStrategy ms =
getEndpoint().getCamelContext().getManagementStrategy();
if (ms != null && ms.getManagementAgent() != null) {
registerKamelets =
ms.getManagementAgent().getRegisterRoutesCreateByKamelet();
diff --git
a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletReifier.java
b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletReifier.java
index 0252e6f92d8..8b0106fac79 100644
---
a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletReifier.java
+++
b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletReifier.java
@@ -20,6 +20,7 @@ import org.apache.camel.Processor;
import org.apache.camel.Route;
import org.apache.camel.model.KameletDefinition;
import org.apache.camel.reifier.ProcessorReifier;
+import org.apache.camel.spi.NodeIdFactory;
import org.apache.camel.support.PluginHelper;
public class KameletReifier extends ProcessorReifier<KameletDefinition> {
@@ -36,9 +37,15 @@ public class KameletReifier extends
ProcessorReifier<KameletDefinition> {
processor = new NoopProcessor();
}
// wrap in uow
- Processor target = new KameletProcessor(camelContext,
parseString(definition.getName()), processor);
- target = PluginHelper.getInternalProcessorFactory(camelContext)
- .addUnitOfWorkProcessorAdvice(camelContext, target, null);
- return target;
+ String outputId =
definition.idOrCreate(camelContext.getCamelContextExtension().getContextPlugin(NodeIdFactory.class));
+ camelContext.getCamelContextExtension().createProcessor(outputId);
+ try {
+ Processor target = new KameletProcessor(camelContext,
parseString(definition.getName()), processor);
+ target = PluginHelper.getInternalProcessorFactory(camelContext)
+ .addUnitOfWorkProcessorAdvice(camelContext, target, null);
+ return target;
+ } finally {
+ camelContext.getCamelContextExtension().createProcessor(null);
+ }
}
}
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
index ba78c36d58a..6f47af18db4 100644
---
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
@@ -37,7 +37,11 @@ public class KameletNoErrorHandlerTest extends
CamelTestSupport {
protected RoutesBuilder createRouteBuilder() {
return new RouteBuilder() {
@Override
- public void configure() {
+ public void configure() throws Exception {
+
+ // enable no error handler
+ customize(KameletComponent.class, k ->
k.setNoErrorHandler(true));
+
routeTemplate("echo")
.templateParameter("prefix")
.from("kamelet:source")
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/KameletRouteSingleTest.java
similarity index 70%
copy from
components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletNoErrorHandlerTest.java
copy to
components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletRouteSingleTest.java
index ba78c36d58a..13eea44ca3d 100644
---
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/KameletRouteSingleTest.java
@@ -16,23 +16,30 @@
*/
package org.apache.camel.component.kamelet;
+import java.util.UUID;
+
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 {
+import static org.assertj.core.api.Assertions.assertThat;
+public class KameletRouteSingleTest extends CamelTestSupport {
@Test
- public void testNoErrorHandler() throws Exception {
- getMockEndpoint("mock:dead").expectedMessageCount(1);
-
- template.sendBody("direct:start", "Hello World");
+ public void testSingle() {
+ String body = UUID.randomUUID().toString();
- MockEndpoint.assertIsSatisfied(context);
+ assertThat(
+
fluentTemplate.toF("direct:single").withBody(body).request(String.class)).isEqualTo("a-"
+ body);
}
+ // **********************************************
+ //
+ // test set-up
+ //
+ // **********************************************
+
@Override
protected RoutesBuilder createRouteBuilder() {
return new RouteBuilder() {
@@ -41,10 +48,9 @@ public class KameletNoErrorHandlerTest extends
CamelTestSupport {
routeTemplate("echo")
.templateParameter("prefix")
.from("kamelet:source")
- .throwException(new
IllegalArgumentException("Forced"));
+ .setBody().simple("{{prefix}}-${body}");
- from("direct:start").routeId("test")
- .errorHandler(deadLetterChannel("mock:dead"))
+ from("direct:single").routeId("test")
.to("kamelet:echo?prefix=a")
.log("${body}");
}
diff --git
a/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletHttpSinkNoErrorHandlerFalseTest.java
b/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletSinkDeadLetterChannelTest.java
similarity index 57%
rename from
components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletHttpSinkNoErrorHandlerFalseTest.java
rename to
components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletSinkDeadLetterChannelTest.java
index 303f94ea1fe..fd6f95b5072 100644
---
a/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletHttpSinkNoErrorHandlerFalseTest.java
+++
b/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletSinkDeadLetterChannelTest.java
@@ -16,29 +16,20 @@
*/
package org.apache.camel.component.kamelet;
-import java.net.UnknownHostException;
-
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;
-import static org.junit.jupiter.api.Assertions.assertInstanceOf;
-import static org.junit.jupiter.api.Assertions.fail;
-
-public class KameletHttpSinkNoErrorHandlerFalseTest extends CamelTestSupport {
+public class KameletSinkDeadLetterChannelTest extends CamelTestSupport {
@Test
- public void testHttpSink() throws Exception {
- getMockEndpoint("mock:dead").expectedMessageCount(0);
+ public void testDeadLetterChannel() throws Exception {
+ getMockEndpoint("mock:dead").expectedMessageCount(1);
+ getMockEndpoint("mock:result").expectedMessageCount(0);
- try {
- template.sendBody("direct:start", "Hello World");
- fail("Should throw exception");
- } catch (Exception e) {
- assertInstanceOf(UnknownHostException.class, e.getCause());
- }
+ template.sendBody("direct:start", "Hello World");
MockEndpoint.assertIsSatisfied(context);
}
@@ -48,17 +39,17 @@ public class KameletHttpSinkNoErrorHandlerFalseTest extends
CamelTestSupport {
return new RouteBuilder() {
@Override
public void configure() {
- routeTemplate("myhttp")
- .templateParameter("url")
+ routeTemplate("fail")
.from("kamelet:source")
- .removeHeaders("*")
- .to("{{url}}");
+ .throwException(new
IllegalArgumentException("Forced"));
- from("direct:start").routeId("test")
- .errorHandler(deadLetterChannel("mock:dead"))
-
.kamelet("myhttp?noErrorHandler=false&url=https://webhook.unknownhost.sitessss/")
- .log("${body}");
+ errorHandler(deadLetterChannel("mock:dead"));
+
+ from("direct:start").routeId("start")
+ .to("kamelet:fail")
+ .to("mock:result");
}
};
}
+
}
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/KameletSourceDeadLetterChannelTest.java
similarity index 73%
copy from
components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletNoErrorHandlerTest.java
copy to
components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletSourceDeadLetterChannelTest.java
index ba78c36d58a..d6f03b01b4e 100644
---
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/KameletSourceDeadLetterChannelTest.java
@@ -22,13 +22,12 @@ 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 {
+public class KameletSourceDeadLetterChannelTest extends CamelTestSupport {
@Test
- public void testNoErrorHandler() throws Exception {
+ public void testDeadLetterChannel() throws Exception {
getMockEndpoint("mock:dead").expectedMessageCount(1);
-
- template.sendBody("direct:start", "Hello World");
+ getMockEndpoint("mock:result").expectedMessageCount(0);
MockEndpoint.assertIsSatisfied(context);
}
@@ -38,16 +37,16 @@ public class KameletNoErrorHandlerTest extends
CamelTestSupport {
return new RouteBuilder() {
@Override
public void configure() {
- routeTemplate("echo")
- .templateParameter("prefix")
- .from("kamelet:source")
+ routeTemplate("fail")
+ .from("timer:fail?delay=0&repeatCount=1")
.throwException(new
IllegalArgumentException("Forced"));
- from("direct:start").routeId("test")
- .errorHandler(deadLetterChannel("mock:dead"))
- .to("kamelet:echo?prefix=a")
- .log("${body}");
+ errorHandler(deadLetterChannel("mock:dead"));
+
+ from("kamelet:fail").routeId("start")
+ .to("mock:result");
}
};
}
+
}
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/KameletTryCatchTest.java
similarity index 94%
rename from
components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletNoErrorHandlerDirectTest.java
rename to
components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletTryCatchTest.java
index 371f1140308..f7aad8bf08d 100644
---
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/KameletTryCatchTest.java
@@ -22,10 +22,10 @@ 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 {
+public class KameletTryCatchTest extends CamelTestSupport {
@Test
- public void testNoErrorHandler() throws Exception {
+ public void testTryCatch() throws Exception {
getMockEndpoint("mock:catch").expectedMessageCount(1);
getMockEndpoint("mock:dead").expectedMessageCount(0);
diff --git a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
index 16103a4ff5f..c67f56a7a81 100644
--- a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
@@ -646,6 +646,24 @@ public interface CamelContext extends
CamelContextLifecycle, RuntimeConfiguratio
String routeId, String routeTemplateId, String prefixId,
RouteTemplateContext routeTemplateContext)
throws Exception;
+ /**
+ * Adds a new route from a given kamelet
+ *
+ * @param routeId the id of the new route to add (optional)
+ * @param routeTemplateId the id of the kamelet route template
(mandatory)
+ * @param prefixId prefix to use for all node ids (not route
id). Use null for no prefix. (optional)
+ * @param parentRouteId the id of the route which is using the
kamelet (such as from / to)
+ * @param parentProcessorId the id of the processor which is using the
kamelet (such as to)
+ * @param parameters parameters to use for the route template when
creating the new route
+ * @return the id of the route added (for example when
an id was auto assigned)
+ * @throws Exception is thrown if error creating and adding the
new route
+ */
+ String addRouteFromKamelet(
+ String routeId, String routeTemplateId, String prefixId,
+ String parentRouteId, String parentProcessorId,
+ Map<String, Object> parameters)
+ throws Exception;
+
/**
* Removes the route templates matching the pattern
*
diff --git
a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
index a03bad961fb..c673400b442 100644
--- a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
@@ -122,9 +122,46 @@ public interface ExtendedCamelContext {
* {@link CamelContext} itself is in started state.
*
* @return <tt>true</tt> if current thread is setting up route(s), or
<tt>false</tt> if not.
+ * @see #setupRoutes(boolean)
*/
boolean isSetupRoutes();
+ /**
+ * Method to signal to {@link CamelContext} that the process to create
routes is in progress.
+ *
+ * @param routeId the current id of the route being created
+ * @see #getCreateRoute()
+ */
+ void createRoute(String routeId);
+
+ /**
+ * Indicates whether current thread is creating a route as part of
starting Camel.
+ * <p/>
+ * This can be useful to know by {@link LifecycleStrategy} or the likes,
in case they need to react differently.
+ *
+ * @return the route id currently being created/started, or <tt>null</tt>
if not.
+ * @see #createRoute(String)
+ */
+ String getCreateRoute();
+
+ /**
+ * Method to signal to {@link CamelContext} that creation of a given
processor is in progress.
+ *
+ * @param processorId the current id of the processor being created
+ * @see #getCreateProcessor()
+ */
+ void createProcessor(String processorId);
+
+ /**
+ * Indicates whether current thread is creating a processor as part of
starting Camel.
+ * <p/>
+ * This can be useful to know by {@link LifecycleStrategy} or the likes,
in case they need to react differently.
+ *
+ * @return the current id of the processor being created
+ * @see #createProcessor(String)
+ */
+ String getCreateProcessor();
+
/**
* Registers a {@link org.apache.camel.spi.EndpointStrategy callback} to
allow you to do custom logic when an
* {@link Endpoint} is about to be registered to the {@link
org.apache.camel.spi.EndpointRegistry}.
diff --git
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultCamelContextExtension.java
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultCamelContextExtension.java
index 6f8557fc90a..b4752104bce 100644
---
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultCamelContextExtension.java
+++
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultCamelContextExtension.java
@@ -91,6 +91,8 @@ import org.slf4j.LoggerFactory;
class DefaultCamelContextExtension implements ExtendedCamelContext {
private final AbstractCamelContext camelContext;
+ private final ThreadLocal<String> isCreateRoute = new ThreadLocal<>();
+ private final ThreadLocal<String> isCreateProcessor = new ThreadLocal<>();
private final ThreadLocal<Boolean> isSetupRoutes = new ThreadLocal<>();
private final List<InterceptStrategy> interceptStrategies = new
ArrayList<>();
private final Map<String, FactoryFinder> factories = new
ConcurrentHashMap<>();
@@ -307,6 +309,16 @@ class DefaultCamelContextExtension implements
ExtendedCamelContext {
return answer != null && answer;
}
+ @Override
+ public String getCreateRoute() {
+ return isCreateRoute.get();
+ }
+
+ @Override
+ public String getCreateProcessor() {
+ return isCreateProcessor.get();
+ }
+
@Override
public void addBootstrap(BootstrapCloseable bootstrap) {
bootstraps.add(bootstrap);
@@ -393,6 +405,24 @@ class DefaultCamelContextExtension implements
ExtendedCamelContext {
this.registry = registry;
}
+ @Override
+ public void createRoute(String routeId) {
+ if (routeId != null) {
+ isCreateRoute.set(routeId);
+ } else {
+ isSetupRoutes.remove();
+ }
+ }
+
+ @Override
+ public void createProcessor(String processorId) {
+ if (processorId != null) {
+ isCreateProcessor.set(processorId);
+ } else {
+ isCreateProcessor.remove();
+ }
+ }
+
@Override
public void setupRoutes(boolean done) {
if (done) {
diff --git
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/InternalServiceManager.java
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/InternalServiceManager.java
index a55d55d62f3..097ef832b56 100644
---
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/InternalServiceManager.java
+++
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/InternalServiceManager.java
@@ -98,17 +98,17 @@ final class InternalServiceManager {
if (object instanceof Service service) {
if (useLifecycleStrategies) {
for (LifecycleStrategy strategy :
camelContext.getLifecycleStrategies()) {
+ Route route;
+ if (service instanceof RouteAware routeAware) {
+ route = routeAware.getRoute();
+ } else {
+ // if the service is added while creating a new route
then grab the route from the startup manager
+ route = internalRouteStartupManager.getSetupRoute();
+ }
if (service instanceof Endpoint endpoint) {
// use specialized endpoint add
strategy.onEndpointAdd(endpoint);
} else {
- Route route;
- if (service instanceof RouteAware routeAware) {
- route = routeAware.getRoute();
- } else {
- // if the service is added while creating a new
route then grab the route from the startup manager
- route =
internalRouteStartupManager.getSetupRoute();
- }
strategy.onServiceAdd(camelContext, service, route);
}
}
diff --git
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
index 77cb3275d65..8cdc1ecf083 100644
---
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
+++
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
@@ -773,6 +773,14 @@ public class SimpleCamelContext extends
AbstractCamelContext {
throw new UnsupportedOperationException();
}
+ @Override
+ public String addRouteFromKamelet(
+ String routeId, String routeTemplateId, String prefixId, String
parentRouteId, String parentProcessorId,
+ Map<String, Object> parameters)
+ throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public void removeRouteTemplates(String pattern) throws Exception {
throw new UnsupportedOperationException();
diff --git
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index 950e5686a6f..6b381c80369 100644
---
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -316,13 +316,11 @@ public class DefaultCamelContext extends
SimpleCamelContext implements ModelCame
@Override
public void addRouteTemplateDefinition(RouteTemplateDefinition
routeTemplateDefinition) throws Exception {
-
model.addRouteTemplateDefinition(routeTemplateDefinition);
}
@Override
public void
removeRouteTemplateDefinitions(Collection<RouteTemplateDefinition>
routeTemplateDefinitions) throws Exception {
-
if (!isLockModel()) {
model.removeRouteTemplateDefinitions(routeTemplateDefinitions);
}
@@ -344,21 +342,18 @@ public class DefaultCamelContext extends
SimpleCamelContext implements ModelCame
@Override
public void addRouteTemplateDefinitionConverter(String templateIdPattern,
RouteTemplateDefinition.Converter converter) {
-
model.addRouteTemplateDefinitionConverter(templateIdPattern,
converter);
}
@Override
public String addRouteFromTemplate(String routeId, String routeTemplateId,
Map<String, Object> parameters)
throws Exception {
-
return model.addRouteFromTemplate(routeId, routeTemplateId,
parameters);
}
@Override
public String addRouteFromTemplate(String routeId, String routeTemplateId,
String prefixId, Map<String, Object> parameters)
throws Exception {
-
return model.addRouteFromTemplate(routeId, routeTemplateId, prefixId,
parameters);
}
@@ -366,20 +361,30 @@ public class DefaultCamelContext extends
SimpleCamelContext implements ModelCame
public String addRouteFromTemplate(
String routeId, String routeTemplateId, String prefixId,
RouteTemplateContext routeTemplateContext)
throws Exception {
-
return model.addRouteFromTemplate(routeId, routeTemplateId, prefixId,
routeTemplateContext);
}
@Override
- public void addRouteFromTemplatedRoute(TemplatedRouteDefinition
templatedRouteDefinition)
+ public String addRouteFromKamelet(
+ String routeId, String routeTemplateId, String prefixId,
+ String parentRouteId, String parentProcessorId, Map<String,
Object> parameters)
throws Exception {
+ return model.addRouteFromKamelet(routeId, routeTemplateId, prefixId,
parentRouteId, parentProcessorId, parameters);
+ }
+
+ @Override
+ public void
addRouteFromTemplatedRoutes(Collection<TemplatedRouteDefinition>
templatedRouteDefinitions) throws Exception {
+ model.addRouteFromTemplatedRoutes(templatedRouteDefinitions);
+ }
+ @Override
+ public void addRouteFromTemplatedRoute(TemplatedRouteDefinition
templatedRouteDefinition)
+ throws Exception {
model.addRouteFromTemplatedRoute(templatedRouteDefinition);
}
@Override
public void removeRouteTemplates(String pattern) throws Exception {
-
if (!isLockModel()) {
model.removeRouteTemplateDefinitions(pattern);
}
@@ -723,6 +728,9 @@ public class DefaultCamelContext extends SimpleCamelContext
implements ModelCame
StartupStepRecorder recorder
=
getCamelContextReference().getCamelContextExtension().getStartupStepRecorder();
StartupStep step = recorder.beginStep(Route.class,
routeDefinition.getRouteId(), "Create Route");
+
+
getCamelContextExtension().createRoute(routeDefinition.getRouteId());
+
Route route =
model.getModelReifierFactory().createRoute(this, routeDefinition);
recorder.endStep(step);
@@ -750,6 +758,7 @@ public class DefaultCamelContext extends SimpleCamelContext
implements ModelCame
if (!alreadyStartingRoutes) {
setStartingRoutes(false);
}
+ getCamelContextExtension().createRoute(null);
pc.setLocalProperties(null);
if (localBeans != null) {
localBeans.setLocalBeanRepository(null);
@@ -852,7 +861,6 @@ public class DefaultCamelContext extends SimpleCamelContext
implements ModelCame
this.getCamelContextExtension().getBootstrapFactoryFinder(),
ModelReifierFactory.FACTORY,
ModelReifierFactory.class);
-
return result.orElseGet(DefaultModelReifierFactory::new);
}
diff --git
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
index 03db1eb3f9a..7da3b7d416e 100644
---
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
+++
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
@@ -428,6 +428,26 @@ public class DefaultModel implements Model {
String routeId, String routeTemplateId, String prefixId,
RouteTemplateContext routeTemplateContext)
throws Exception {
+ return doAddRouteFromTemplate(routeId, routeTemplateId, prefixId,
null, null, routeTemplateContext);
+ }
+
+ @Override
+ public String addRouteFromKamelet(
+ String routeId, String routeTemplateId, String prefixId,
+ String parentRouteId, String parentProcessorId, Map<String,
Object> parameters)
+ throws Exception {
+ RouteTemplateContext rtc = new
DefaultRouteTemplateContext(camelContext);
+ if (parameters != null) {
+ parameters.forEach(rtc::setParameter);
+ }
+ return doAddRouteFromTemplate(routeId, routeTemplateId, prefixId,
parentRouteId, parentProcessorId, rtc);
+ }
+
+ protected String doAddRouteFromTemplate(
+ String routeId, String routeTemplateId, String prefixId,
+ String parentRouteId, String parentProcessorId,
+ RouteTemplateContext routeTemplateContext)
+ throws Exception {
RouteTemplateDefinition target = null;
for (RouteTemplateDefinition def : routeTemplateDefinitions) {
@@ -515,6 +535,12 @@ public class DefaultModel implements Model {
}
}
+ if (parentRouteId != null) {
+ addProperty(prop, "parentRouteId", parentRouteId);
+ }
+ if (parentProcessorId != null) {
+ addProperty(prop, "parentProcessorId", parentProcessorId);
+ }
RouteDefinition def = converter.apply(target, prop);
if (routeId != null) {
def.setId(routeId);
diff --git
a/core/camel-core-model/src/main/java/org/apache/camel/model/Model.java
b/core/camel-core-model/src/main/java/org/apache/camel/model/Model.java
index efbf693be2a..e225426a324 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/Model.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/Model.java
@@ -253,6 +253,24 @@ public interface Model {
RouteTemplateContext routeTemplateContext)
throws Exception;
+ /**
+ * Adds a new route from a given kamelet
+ *
+ * @param routeId the id of the new route to add (optional)
+ * @param routeTemplateId the id of the kamelet route template
(mandatory)
+ * @param prefixId prefix to use when assigning route and node
IDs (optional)
+ * @param parentRouteId the id of the route which is using the
kamelet (such as from / to)
+ * @param parentProcessorId the id of the processor which is using the
kamelet (such as to)
+ * @param parameters parameters to use for the route template when
creating the new route
+ * @return the id of the route added (for example when
an id was auto assigned)
+ * @throws Exception is thrown if error creating and adding the
new route
+ */
+ String addRouteFromKamelet(
+ String routeId, String routeTemplateId, String prefixId,
+ String parentRouteId, String parentProcessorId,
+ Map<String, Object> parameters)
+ throws Exception;
+
/**
* Adds a new route from a given templated route definition
*
diff --git
a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
index 8d7a17f981c..5172592716d 100644
---
a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
+++
b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
@@ -22,8 +22,10 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
+import org.apache.camel.CamelContext;
import org.apache.camel.NamedNode;
import org.apache.camel.spi.Resource;
+import org.apache.camel.support.CamelContextHelper;
import org.apache.camel.support.ResourceHelper;
import org.apache.camel.util.FileUtil;
@@ -473,4 +475,57 @@ public final class ProcessorDefinitionHelper {
return answer;
}
+ /**
+ * Whether the model should be wrapped in an error handler or not.
+ *
+ * Some EIPs like try/catch, circuit breaker, multicast, and kamelets have
impact on whether the model should be
+ * wrapped or not.
+ */
+ public static boolean shouldWrapInErrorHandler(
+ CamelContext context, ProcessorDefinition<?> definition,
+ ProcessorDefinition<?> child, Boolean inheritErrorHandler) {
+ boolean wrap = false;
+
+ // set the error handler, must be done after init as we can set the
+ // error handler as first in the chain
+ if (definition instanceof TryDefinition || definition instanceof
CatchDefinition
+ || definition instanceof FinallyDefinition) {
+ // do not use error handler for try .. catch .. finally blocks as
it
+ // will handle errors itself
+ } else if
(ProcessorDefinitionHelper.isParentOfType(TryDefinition.class, definition, true)
+ ||
ProcessorDefinitionHelper.isParentOfType(CatchDefinition.class, definition,
true)
+ ||
ProcessorDefinitionHelper.isParentOfType(FinallyDefinition.class, definition,
true)) {
+ // do not use error handler for try .. catch .. finally blocks as
it
+ // will handle errors itself
+ // by checking that any of our parent(s) is not a try .. catch or
+ // finally type
+ } else if (definition instanceof OnExceptionDefinition
+ ||
ProcessorDefinitionHelper.isParentOfType(OnExceptionDefinition.class,
definition, true)) {
+ // do not use error handler for onExceptions blocks as it will
+ // handle errors itself
+ } else if (definition instanceof CircuitBreakerDefinition
+ ||
ProcessorDefinitionHelper.isParentOfType(CircuitBreakerDefinition.class,
definition, true)) {
+ // do not use error handler for circuit breaker
+ // however if inherit error handler is enabled, we need to wrap an
error handler on the parent
+ if (inheritErrorHandler != null && inheritErrorHandler && child ==
null) {
+ // only wrap the parent (not the children of the circuit
breaker)
+ wrap = true;
+ }
+ } else if (definition instanceof MulticastDefinition def) {
+ // do not use error handler for multicast as it offers fine-grained
+ // error handlers for its outputs
+ // however if share unit of work is enabled, we need to wrap an
+ // error handler on the multicast parent
+ Boolean isShareUnitOfWork =
CamelContextHelper.parseBoolean(context, def.getShareUnitOfWork());
+ if (isShareUnitOfWork != null && isShareUnitOfWork && child ==
null) {
+ // only wrap the parent (not the children of the multicast)
+ wrap = true;
+ }
+ } else {
+ // use error handler by default or if configured to do so
+ wrap = true;
+ }
+ return wrap;
+ }
+
}
diff --git
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ProcessorReifier.java
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ProcessorReifier.java
index 8df133008ff..b30fe7c4194 100644
---
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ProcessorReifier.java
+++
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ProcessorReifier.java
@@ -694,54 +694,9 @@ public abstract class ProcessorReifier<T extends
ProcessorDefinition<?>> extends
// initialize the channel
channel.initChannel(this.route, definition, child, interceptors,
processor, route, first);
- boolean wrap = false;
// set the error handler, must be done after init as we can set the
// error handler as first in the chain
- if (definition instanceof TryDefinition || definition instanceof
CatchDefinition
- || definition instanceof FinallyDefinition) {
- // do not use error handler for try .. catch .. finally blocks as
it
- // will handle errors itself
- LOG.trace("{} is part of doTry .. doCatch .. doFinally so no error
handler is applied", definition);
- } else if
(ProcessorDefinitionHelper.isParentOfType(TryDefinition.class, definition, true)
- ||
ProcessorDefinitionHelper.isParentOfType(CatchDefinition.class, definition,
true)
- ||
ProcessorDefinitionHelper.isParentOfType(FinallyDefinition.class, definition,
true)) {
- // do not use error handler for try .. catch .. finally blocks as
it
- // will handle errors itself
- // by checking that any of our parent(s) is not a try .. catch or
- // finally type
- LOG.trace("{} is part of doTry .. doCatch .. doFinally so no error
handler is applied", definition);
- } else if (definition instanceof OnExceptionDefinition
- ||
ProcessorDefinitionHelper.isParentOfType(OnExceptionDefinition.class,
definition, true)) {
- LOG.trace("{} is part of OnException so no error handler is
applied", definition);
- // do not use error handler for onExceptions blocks as it will
- // handle errors itself
- } else if (definition instanceof CircuitBreakerDefinition
- ||
ProcessorDefinitionHelper.isParentOfType(CircuitBreakerDefinition.class,
definition, true)) {
- // do not use error handler for circuit breaker
- // however if inherit error handler is enabled, we need to wrap an
error handler on the parent
- if (inheritErrorHandler != null && inheritErrorHandler && child ==
null) {
- // only wrap the parent (not the children of the circuit
breaker)
- wrap = true;
- } else {
- LOG.trace("{} is part of CircuitBreaker so no error handler is
applied", definition);
- }
- } else if (definition instanceof MulticastDefinition def) {
- // do not use error handler for multicast as it offers fine-grained
- // error handlers for its outputs
- // however if share unit of work is enabled, we need to wrap an
- // error handler on the multicast parent
- boolean isShareUnitOfWork = parseBoolean(def.getShareUnitOfWork(),
false);
- if (isShareUnitOfWork && child == null) {
- // only wrap the parent (not the children of the multicast)
- wrap = true;
- } else {
- LOG.trace("{} is part of multicast which have special error
handling so no error handler is applied",
- definition);
- }
- } else {
- // use error handler by default or if configured to do so
- wrap = true;
- }
+ boolean wrap =
ProcessorDefinitionHelper.shouldWrapInErrorHandler(camelContext, definition,
child, inheritErrorHandler);
if (wrap) {
wrapChannelInErrorHandler(channel, inheritErrorHandler);
}
@@ -851,17 +806,22 @@ public abstract class ProcessorReifier<T extends
ProcessorDefinition<?>> extends
StartupStep step =
camelContext.getCamelContextExtension().getStartupStepRecorder().beginStep(ProcessorReifier.class,
outputId, "Create processor");
+ camelContext.getCamelContextExtension().createProcessor(outputId);
Processor processor = null;
- // at first use custom factory
- final ProcessorFactory processorFactory =
PluginHelper.getProcessorFactory(camelContext);
- if (processorFactory != null) {
- processor = processorFactory.createProcessor(route, output);
- }
- // fallback to default implementation if factory did not create the
processor
- if (processor == null) {
- processor = reifier(route, output).createProcessor();
+ try {
+ // at first use custom factory
+ final ProcessorFactory processorFactory =
PluginHelper.getProcessorFactory(camelContext);
+ if (processorFactory != null) {
+ processor = processorFactory.createProcessor(route, output);
+ }
+ // fallback to default implementation if factory did not create
the processor
+ if (processor == null) {
+ processor = reifier(route, output).createProcessor();
+ }
+
camelContext.getCamelContextExtension().getStartupStepRecorder().endStep(step);
+ } finally {
+ camelContext.getCamelContextExtension().createProcessor(null);
}
-
camelContext.getCamelContextExtension().getStartupStepRecorder().endStep(step);
return processor;
}
@@ -869,36 +829,42 @@ public abstract class ProcessorReifier<T extends
ProcessorDefinition<?>> extends
* Creates the processor and wraps it in any necessary interceptors and
error handlers
*/
protected Channel makeProcessor() throws Exception {
- Processor processor = null;
+ String outputId =
definition.idOrCreate(camelContext.getCamelContextExtension().getContextPlugin(NodeIdFactory.class));
+ camelContext.getCamelContextExtension().createProcessor(outputId);
+ try {
+ Processor processor = null;
- // allow any custom logic before we create the processor
- preCreateProcessor();
+ // allow any custom logic before we create the processor
+ preCreateProcessor();
- // at first use custom factory
- final ProcessorFactory processorFactory =
PluginHelper.getProcessorFactory(camelContext);
- if (processorFactory != null) {
- processor = processorFactory.createProcessor(route, definition);
- }
- // fallback to default implementation if factory did not create the
- // processor
- if (processor == null) {
- processor = createProcessor();
- }
+ // at first use custom factory
+ final ProcessorFactory processorFactory =
PluginHelper.getProcessorFactory(camelContext);
+ if (processorFactory != null) {
+ processor = processorFactory.createProcessor(route,
definition);
+ }
+ // fallback to default implementation if factory did not create the
+ // processor
+ if (processor == null) {
+ processor = createProcessor();
+ }
- // inject id
- if (processor instanceof IdAware idAware) {
- String id = getId(definition);
- idAware.setId(id);
- }
- if (processor instanceof RouteIdAware routeIdAware) {
- routeIdAware.setRouteId(route.getRouteId());
- }
+ // inject id
+ if (processor instanceof IdAware idAware) {
+ String id = getId(definition);
+ idAware.setId(id);
+ }
+ if (processor instanceof RouteIdAware routeIdAware) {
+ routeIdAware.setRouteId(route.getRouteId());
+ }
- if (processor == null) {
- // no processor to make
- return null;
+ if (processor == null) {
+ // no processor to make
+ return null;
+ }
+ return wrapProcessor(processor);
+ } finally {
+ camelContext.getCamelContextExtension().createProcessor(null);
}
- return wrapProcessor(processor);
}
/**
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_10.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_10.adoc
index 5cbb53580a6..6a70780ce33 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_10.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_10.adoc
@@ -88,6 +88,72 @@ Should now be:
</loadBalance>
----
+=== camel-kamelet
+
+The error handling when using kamelets has been refactored to let Kamelets
re-use the same error handling
+that are from the route where the kamelets are being used. Previously Kamelets
did not have
+any error handling.
+
+Suppose you have kamelets that would cause an exception during processing, such
+as the source below. Now because the route has been configured with a _dead
letter channel_
+as the error handler, then the exception from the kamelet will be handled by
the route error handler.
+Which means you will se a WARN being logged.
+
+Previously the exception would **not** be handled by the route error handler,
and the kamelet source
+would always fail internally and cause a WARN being logged. Meaning that you
did not have
+any power to handle these errors.
+
+Now the kamelets are _first class_ and gives users the full power to handle
errors as they see fit.
+
+[source,yaml]
+----
+- route:
+ errorHandler:
+ deadLetterChannel:
+ deadLetterUri: log:dead?level=WARN
+ id: myRoute
+ from:
+ uri: "kamelet:my-error-source/source"
+ steps:
+ - log: "${body}"
+----
+
+This change has most an effect on source Kamelets. For sink or action Kamelets,
+then any error would be propagated back to the route, that could still handle
the error.
+However, if the error handler is configured to perform retries, then the retry
would be
+starting all over again calling the sink Kamelet. This change will let the
error handler
+perform retries at the original of the error (also inside the Kamelet), the
same as
+regular Camel routes.
+
+So suppose you have the following route:
+
+[source,yaml]
+----
+- route:
+ errorHandler:
+ deadLetterChannel:
+ deadLetterUri: log:dead?level=WARN
+ redeliveryPolicy:
+ maximumRedeliveries: 5
+ redeliveryDelay: "5000"
+ id: myRoute
+ from:
+ uri: "direct:start"
+ steps:
+ - to:
+ uri: "kamelet:my-error-sink/sink"
+ - log: "${body}"
+----
+
+Then notice the error handler has been configured to do redeliveries up till 5
times with 5 sec delay between.
+Suppose the sink kamelet is throwing an exception, then Camel will now perform
the redelivery attempt
+at the point of origin, which means inside the Kamelet. Previously the
redelivery will
+only happen at the route level, calling the kamelet all over again.
+
+The option `noErrorHandler` has changed default from `true` to `false`. You
should only
+use this option if you want to turn on error handling inside Kamelets all
together. However,
+this should only be used in advanced/rare use-cases. This option may in the
future be deprecated and removed.
+
=== camel-azure-files
The class `org.apache.camel.component.file.azure.FilesHeaders` has been
renamed to `org.apache.camel.component.file.azure.FilesConstants`.
diff --git
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/KameletComponentBuilderFactory.java
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/KameletComponentBuilderFactory.java
index 4a130be69d6..c2df77bea30 100644
---
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/KameletComponentBuilderFactory.java
+++
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/KameletComponentBuilderFactory.java
@@ -213,13 +213,18 @@ public interface KameletComponentBuilderFactory {
/**
- * 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.
+ * Whether kamelets should use error handling or not. By default, the
+ * Kamelet uses the same error handler as from the calling route. This
+ * means that if the calling route has error handling that performs
+ * retries, or routing to a dead letter channel, then the kamelet route
+ * will use this also. This can be turned off by setting this option to
+ * true. If off then the kamelet route is not using error handling, and
+ * any exception thrown will for source kamelets be logged by the
+ * consumer, and the sink/action kamelets will fail processing.
*
* The option is a: <code>boolean</code> type.
*
- * Default: true
+ * Default: false
* Group: advanced
*
* @param noErrorHandler the value to set
diff --git
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/KameletEndpointBuilderFactory.java
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/KameletEndpointBuilderFactory.java
index 08024723566..c0782f87929 100644
---
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/KameletEndpointBuilderFactory.java
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/KameletEndpointBuilderFactory.java
@@ -189,13 +189,18 @@ public interface KameletEndpointBuilderFactory {
return this;
}
/**
- * 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.
+ * Whether kamelets should use error handling or not. By default, the
+ * Kamelet uses the same error handler as from the calling route. This
+ * means that if the calling route has error handling that performs
+ * retries, or routing to a dead letter channel, then the kamelet route
+ * will use this also. This can be turned off by setting this option to
+ * true. If off then the kamelet route is not using error handling, and
+ * any exception thrown will for source kamelets be logged by the
+ * consumer, and the sink/action kamelets will fail processing.
*
* The option is a: <code>boolean</code> type.
*
- * Default: true
+ * Default: false
* Group: advanced
*
* @param noErrorHandler the value to set
@@ -206,13 +211,18 @@ public interface KameletEndpointBuilderFactory {
return this;
}
/**
- * 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.
+ * Whether kamelets should use error handling or not. By default, the
+ * Kamelet uses the same error handler as from the calling route. This
+ * means that if the calling route has error handling that performs
+ * retries, or routing to a dead letter channel, then the kamelet route
+ * will use this also. This can be turned off by setting this option to
+ * true. If off then the kamelet route is not using error handling, and
+ * any exception thrown will for source kamelets be logged by the
+ * consumer, and the sink/action kamelets will fail processing.
*
* The option will be converted to a <code>boolean</code> type.
*
- * Default: true
+ * Default: false
* Group: advanced
*
* @param noErrorHandler the value to set
@@ -404,13 +414,18 @@ public interface KameletEndpointBuilderFactory {
return this;
}
/**
- * 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.
+ * Whether kamelets should use error handling or not. By default, the
+ * Kamelet uses the same error handler as from the calling route. This
+ * means that if the calling route has error handling that performs
+ * retries, or routing to a dead letter channel, then the kamelet route
+ * will use this also. This can be turned off by setting this option to
+ * true. If off then the kamelet route is not using error handling, and
+ * any exception thrown will for source kamelets be logged by the
+ * consumer, and the sink/action kamelets will fail processing.
*
* The option is a: <code>boolean</code> type.
*
- * Default: true
+ * Default: false
* Group: advanced
*
* @param noErrorHandler the value to set
@@ -421,13 +436,18 @@ public interface KameletEndpointBuilderFactory {
return this;
}
/**
- * 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.
+ * Whether kamelets should use error handling or not. By default, the
+ * Kamelet uses the same error handler as from the calling route. This
+ * means that if the calling route has error handling that performs
+ * retries, or routing to a dead letter channel, then the kamelet route
+ * will use this also. This can be turned off by setting this option to
+ * true. If off then the kamelet route is not using error handling, and
+ * any exception thrown will for source kamelets be logged by the
+ * consumer, and the sink/action kamelets will fail processing.
*
* The option will be converted to a <code>boolean</code> type.
*
- * Default: true
+ * Default: false
* Group: advanced
*
* @param noErrorHandler the value to set
@@ -481,13 +501,18 @@ public interface KameletEndpointBuilderFactory {
return this;
}
/**
- * 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.
+ * Whether kamelets should use error handling or not. By default, the
+ * Kamelet uses the same error handler as from the calling route. This
+ * means that if the calling route has error handling that performs
+ * retries, or routing to a dead letter channel, then the kamelet route
+ * will use this also. This can be turned off by setting this option to
+ * true. If off then the kamelet route is not using error handling, and
+ * any exception thrown will for source kamelets be logged by the
+ * consumer, and the sink/action kamelets will fail processing.
*
* The option is a: <code>boolean</code> type.
*
- * Default: true
+ * Default: false
* Group: advanced
*
* @param noErrorHandler the value to set
@@ -498,13 +523,18 @@ public interface KameletEndpointBuilderFactory {
return this;
}
/**
- * 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.
+ * Whether kamelets should use error handling or not. By default, the
+ * Kamelet uses the same error handler as from the calling route. This
+ * means that if the calling route has error handling that performs
+ * retries, or routing to a dead letter channel, then the kamelet route
+ * will use this also. This can be turned off by setting this option to
+ * true. If off then the kamelet route is not using error handling, and
+ * any exception thrown will for source kamelets be logged by the
+ * consumer, and the sink/action kamelets will fail processing.
*
* The option will be converted to a <code>boolean</code> type.
*
- * Default: true
+ * Default: false
* Group: advanced
*
* @param noErrorHandler the value to set