This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch once in repository https://gitbox.apache.org/repos/asf/camel.git
commit bd5e6fa7a8269330b4f455539aff05872d67d544 Author: Claus Ibsen <[email protected]> AuthorDate: Thu Dec 18 07:54:35 2025 +0100 CAMEL-22431: camel-once - A component for development to trigger only once --- .../org/apache/camel/catalog/components/once.json | 6 +- .../component/once/OnceEndpointConfigurer.java | 15 +++ .../component/once/OnceEndpointUriFactory.java | 9 +- .../org/apache/camel/component/once/once.json | 6 +- .../apache/camel/component/once/OnceConsumer.java | 28 +++-- .../apache/camel/component/once/OnceEndpoint.java | 34 +++++- .../endpoint/dsl/OnceEndpointBuilderFactory.java | 126 ++++++++++++++++++--- 7 files changed, 196 insertions(+), 28 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/once.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/once.json index 690afc34f39c..909c42b0f30e 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/once.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/once.json @@ -30,9 +30,11 @@ "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The logical name" }, "body": { "index": 1, "kind": "parameter", "displayName": "Body", "group": "consumer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "The data to use as message body. You can externalize the data by using file: or classpath: as prefix and specify the location of the file." }, - "delay": { "index": 2, "kind": "parameter", "displayName": "Delay", "group": "consumer", "label": "", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "The number of milliseconds to wait before triggering. The default value is 1000." }, + "headers": { "index": 2, "kind": "parameter", "displayName": "Headers", "group": "consumer", "label": "", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "header.", "multiValue": true, "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "The data to use as message headers as key=value pairs. You can externalize the data by using file: or classpath: [...] "bridgeErrorHandler": { "index": 3, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming [...] "exceptionHandler": { "index": 4, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...] - "exchangePattern": { "index": 5, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." } + "exchangePattern": { "index": 5, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, + "delay": { "index": 6, "kind": "parameter", "displayName": "Delay", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "The number of milliseconds to wait before triggering. The default value is 1000." }, + "variables": { "index": 7, "kind": "parameter", "displayName": "Variables", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "variable.", "multiValue": true, "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "The data to use as exchange variables as key=value pairs. You can externalize the data by using fi [...] } } diff --git a/components/camel-once/src/generated/java/org/apache/camel/component/once/OnceEndpointConfigurer.java b/components/camel-once/src/generated/java/org/apache/camel/component/once/OnceEndpointConfigurer.java index 629bf407ee8e..ab494fa200b2 100644 --- a/components/camel-once/src/generated/java/org/apache/camel/component/once/OnceEndpointConfigurer.java +++ b/components/camel-once/src/generated/java/org/apache/camel/component/once/OnceEndpointConfigurer.java @@ -31,6 +31,8 @@ public class OnceEndpointConfigurer extends PropertyConfigurerSupport implements case "exceptionHandler": target.setExceptionHandler(property(camelContext, org.apache.camel.spi.ExceptionHandler.class, value)); return true; case "exchangepattern": case "exchangePattern": target.setExchangePattern(property(camelContext, org.apache.camel.ExchangePattern.class, value)); return true; + case "headers": target.setHeaders(property(camelContext, java.util.Map.class, value)); return true; + case "variables": target.setVariables(property(camelContext, java.util.Map.class, value)); return true; default: return false; } } @@ -46,6 +48,8 @@ public class OnceEndpointConfigurer extends PropertyConfigurerSupport implements case "exceptionHandler": return org.apache.camel.spi.ExceptionHandler.class; case "exchangepattern": case "exchangePattern": return org.apache.camel.ExchangePattern.class; + case "headers": return java.util.Map.class; + case "variables": return java.util.Map.class; default: return null; } } @@ -62,6 +66,17 @@ public class OnceEndpointConfigurer extends PropertyConfigurerSupport implements case "exceptionHandler": return target.getExceptionHandler(); case "exchangepattern": case "exchangePattern": return target.getExchangePattern(); + case "headers": return target.getHeaders(); + case "variables": return target.getVariables(); + default: return null; + } + } + + @Override + public Object getCollectionValueType(Object target, String name, boolean ignoreCase) { + switch (ignoreCase ? name.toLowerCase() : name) { + case "headers": return java.lang.Object.class; + case "variables": return java.lang.Object.class; default: return null; } } diff --git a/components/camel-once/src/generated/java/org/apache/camel/component/once/OnceEndpointUriFactory.java b/components/camel-once/src/generated/java/org/apache/camel/component/once/OnceEndpointUriFactory.java index 6d835449c5ce..7e9fc37d7a65 100644 --- a/components/camel-once/src/generated/java/org/apache/camel/component/once/OnceEndpointUriFactory.java +++ b/components/camel-once/src/generated/java/org/apache/camel/component/once/OnceEndpointUriFactory.java @@ -23,16 +23,21 @@ public class OnceEndpointUriFactory extends org.apache.camel.support.component.E private static final Set<String> SECRET_PROPERTY_NAMES; private static final Map<String, String> MULTI_VALUE_PREFIXES; static { - Set<String> props = new HashSet<>(6); + Set<String> props = new HashSet<>(8); props.add("body"); props.add("bridgeErrorHandler"); props.add("delay"); props.add("exceptionHandler"); props.add("exchangePattern"); + props.add("headers"); props.add("name"); + props.add("variables"); PROPERTY_NAMES = Collections.unmodifiableSet(props); SECRET_PROPERTY_NAMES = Collections.emptySet(); - MULTI_VALUE_PREFIXES = Collections.emptyMap(); + Map<String, String> prefixes = new HashMap<>(2); + prefixes.put("headers", "header."); + prefixes.put("variables", "variable."); + MULTI_VALUE_PREFIXES = Collections.unmodifiableMap(prefixes); } @Override diff --git a/components/camel-once/src/generated/resources/META-INF/org/apache/camel/component/once/once.json b/components/camel-once/src/generated/resources/META-INF/org/apache/camel/component/once/once.json index 690afc34f39c..909c42b0f30e 100644 --- a/components/camel-once/src/generated/resources/META-INF/org/apache/camel/component/once/once.json +++ b/components/camel-once/src/generated/resources/META-INF/org/apache/camel/component/once/once.json @@ -30,9 +30,11 @@ "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The logical name" }, "body": { "index": 1, "kind": "parameter", "displayName": "Body", "group": "consumer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "The data to use as message body. You can externalize the data by using file: or classpath: as prefix and specify the location of the file." }, - "delay": { "index": 2, "kind": "parameter", "displayName": "Delay", "group": "consumer", "label": "", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "The number of milliseconds to wait before triggering. The default value is 1000." }, + "headers": { "index": 2, "kind": "parameter", "displayName": "Headers", "group": "consumer", "label": "", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "header.", "multiValue": true, "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "The data to use as message headers as key=value pairs. You can externalize the data by using file: or classpath: [...] "bridgeErrorHandler": { "index": 3, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming [...] "exceptionHandler": { "index": 4, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...] - "exchangePattern": { "index": 5, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." } + "exchangePattern": { "index": 5, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, + "delay": { "index": 6, "kind": "parameter", "displayName": "Delay", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "The number of milliseconds to wait before triggering. The default value is 1000." }, + "variables": { "index": 7, "kind": "parameter", "displayName": "Variables", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "variable.", "multiValue": true, "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "The data to use as exchange variables as key=value pairs. You can externalize the data by using fi [...] } } diff --git a/components/camel-once/src/main/java/org/apache/camel/component/once/OnceConsumer.java b/components/camel-once/src/main/java/org/apache/camel/component/once/OnceConsumer.java index 96da3b1650b7..934c7b1f21f3 100644 --- a/components/camel-once/src/main/java/org/apache/camel/component/once/OnceConsumer.java +++ b/components/camel-once/src/main/java/org/apache/camel/component/once/OnceConsumer.java @@ -22,11 +22,9 @@ import java.util.TimerTask; import org.apache.camel.CamelContext; import org.apache.camel.Exchange; -import org.apache.camel.Expression; import org.apache.camel.Processor; import org.apache.camel.StartupListener; import org.apache.camel.support.DefaultConsumer; -import org.apache.camel.support.LanguageHelper; import org.apache.camel.support.ResourceHelper; import org.apache.camel.util.StringHelper; import org.slf4j.Logger; @@ -86,8 +84,24 @@ public class OnceConsumer extends DefaultConsumer implements StartupListener { public void run() { Exchange exchange = createExchange(false); try { - String body = resolveData(endpoint.getBody()); + Object body = resolveData(endpoint.getBody()); exchange.getMessage().setBody(body); + if (endpoint.getHeaders() != null) { + for (var e : endpoint.getHeaders().entrySet()) { + Object v = resolveData(e.getValue()); + if (v != null) { + exchange.getMessage().setHeader(e.getKey(), v); + } + } + } + if (endpoint.getVariables() != null) { + for (var e : endpoint.getVariables().entrySet()) { + Object v = resolveData(e.getValue()); + if (v != null) { + exchange.setVariable(e.getKey(), v); + } + } + } getProcessor().process(exchange); } catch (Exception e) { exchange.setException(e); @@ -104,10 +118,10 @@ public class OnceConsumer extends DefaultConsumer implements StartupListener { } } - private String resolveData(String data) throws Exception { - String answer = data; - if (ResourceHelper.hasScheme(data)) { - try (InputStream is = ResourceHelper.resolveMandatoryResourceAsInputStream(camelContext, data)) { + private Object resolveData(Object data) throws Exception { + String answer = data instanceof String ? data.toString() : null; + if (ResourceHelper.hasScheme(answer)) { + try (InputStream is = ResourceHelper.resolveMandatoryResourceAsInputStream(camelContext, answer)) { answer = camelContext.getTypeConverter().mandatoryConvertTo(String.class, is); } } diff --git a/components/camel-once/src/main/java/org/apache/camel/component/once/OnceEndpoint.java b/components/camel-once/src/main/java/org/apache/camel/component/once/OnceEndpoint.java index ba1b07bfa729..997a22ef5a40 100644 --- a/components/camel-once/src/main/java/org/apache/camel/component/once/OnceEndpoint.java +++ b/components/camel-once/src/main/java/org/apache/camel/component/once/OnceEndpoint.java @@ -16,6 +16,8 @@ */ package org.apache.camel.component.once; +import java.util.Map; + import org.apache.camel.Category; import org.apache.camel.Component; import org.apache.camel.Consumer; @@ -35,11 +37,17 @@ public class OnceEndpoint extends DefaultEndpoint { @UriPath @Metadata(required = true) private String name; - @UriParam(defaultValue = "1000") + @UriParam(label = "advanced", defaultValue = "1000") private long delay = 1000; @UriParam @Metadata(supportFileReference = true) private String body; + @UriParam(multiValue = true, prefix = "header.") + @Metadata(supportFileReference = true) + private Map<String, Object> headers; + @UriParam(label = "advanced", multiValue = true, prefix = "variable.") + @Metadata(supportFileReference = true) + private Map<String, Object> variables; public OnceEndpoint() { } @@ -106,4 +114,28 @@ public class OnceEndpoint extends DefaultEndpoint { public void setBody(String body) { this.body = body; } + + /** + * The data to use as message headers as key=value pairs. You can externalize the data by using file: or classpath: + * as prefix and specify the location of the file. + */ + public Map<String, Object> getHeaders() { + return headers; + } + + public void setHeaders(Map<String, Object> headers) { + this.headers = headers; + } + + public Map<String, Object> getVariables() { + return variables; + } + + /** + * The data to use as exchange variables as key=value pairs. You can externalize the data by using file: or + * classpath: as prefix and specify the location of the file. + */ + public void setVariables(Map<String, Object> variables) { + this.variables = variables; + } } diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OnceEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OnceEndpointBuilderFactory.java index d4bac6603f14..ea1360cc8930 100644 --- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OnceEndpointBuilderFactory.java +++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OnceEndpointBuilderFactory.java @@ -64,35 +64,52 @@ public interface OnceEndpointBuilderFactory { return this; } /** - * The number of milliseconds to wait before triggering. The default - * value is 1000. + * The data to use as message headers as key=value pairs. You can + * externalize the data by using file: or classpath: as prefix and + * specify the location of the file. This is a multi-value option with + * prefix: header. * - * The option is a: <code>long</code> type. + * This option can also be loaded from an existing file, by prefixing + * with file: or classpath: followed by the location of the file. + * + * The option is a: <code>java.util.Map<java.lang.String, + * java.lang.Object></code> type. + * The option is multivalued, and you can use the headers(String, + * Object) method to add a value (call the method multiple times to set + * more values). * - * Default: 1000 * Group: consumer * - * @param delay the value to set + * @param key the option key + * @param value the option value * @return the dsl builder */ - default OnceEndpointBuilder delay(long delay) { - doSetProperty("delay", delay); + default OnceEndpointBuilder headers(String key, Object value) { + doSetMultiValueProperty("headers", "header." + key, value); return this; } /** - * The number of milliseconds to wait before triggering. The default - * value is 1000. + * The data to use as message headers as key=value pairs. You can + * externalize the data by using file: or classpath: as prefix and + * specify the location of the file. This is a multi-value option with + * prefix: header. * - * The option will be converted to a <code>long</code> type. + * This option can also be loaded from an existing file, by prefixing + * with file: or classpath: followed by the location of the file. + * + * The option is a: <code>java.util.Map<java.lang.String, + * java.lang.Object></code> type. + * The option is multivalued, and you can use the headers(String, + * Object) method to add a value (call the method multiple times to set + * more values). * - * Default: 1000 * Group: consumer * - * @param delay the value to set + * @param values the values * @return the dsl builder */ - default OnceEndpointBuilder delay(String delay) { - doSetProperty("delay", delay); + default OnceEndpointBuilder headers(Map values) { + doSetMultiValueProperties("headers", "header.", values); return this; } } @@ -224,6 +241,87 @@ public interface OnceEndpointBuilderFactory { doSetProperty("exchangePattern", exchangePattern); return this; } + /** + * The number of milliseconds to wait before triggering. The default + * value is 1000. + * + * The option is a: <code>long</code> type. + * + * Default: 1000 + * Group: advanced + * + * @param delay the value to set + * @return the dsl builder + */ + default AdvancedOnceEndpointBuilder delay(long delay) { + doSetProperty("delay", delay); + return this; + } + /** + * The number of milliseconds to wait before triggering. The default + * value is 1000. + * + * The option will be converted to a <code>long</code> type. + * + * Default: 1000 + * Group: advanced + * + * @param delay the value to set + * @return the dsl builder + */ + default AdvancedOnceEndpointBuilder delay(String delay) { + doSetProperty("delay", delay); + return this; + } + /** + * The data to use as exchange variables as key=value pairs. You can + * externalize the data by using file: or classpath: as prefix and + * specify the location of the file. This is a multi-value option with + * prefix: variable. + * + * This option can also be loaded from an existing file, by prefixing + * with file: or classpath: followed by the location of the file. + * + * The option is a: <code>java.util.Map<java.lang.String, + * java.lang.Object></code> type. + * The option is multivalued, and you can use the variables(String, + * Object) method to add a value (call the method multiple times to set + * more values). + * + * Group: advanced + * + * @param key the option key + * @param value the option value + * @return the dsl builder + */ + default AdvancedOnceEndpointBuilder variables(String key, Object value) { + doSetMultiValueProperty("variables", "variable." + key, value); + return this; + } + /** + * The data to use as exchange variables as key=value pairs. You can + * externalize the data by using file: or classpath: as prefix and + * specify the location of the file. This is a multi-value option with + * prefix: variable. + * + * This option can also be loaded from an existing file, by prefixing + * with file: or classpath: followed by the location of the file. + * + * The option is a: <code>java.util.Map<java.lang.String, + * java.lang.Object></code> type. + * The option is multivalued, and you can use the variables(String, + * Object) method to add a value (call the method multiple times to set + * more values). + * + * Group: advanced + * + * @param values the values + * @return the dsl builder + */ + default AdvancedOnceEndpointBuilder variables(Map values) { + doSetMultiValueProperties("variables", "variable.", values); + return this; + } } public interface OnceBuilders {
