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 b2d291a28509 Once (#20506)
b2d291a28509 is described below
commit b2d291a28509f52c706ac56da9834673d53cdc5d
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu Dec 18 13:43:15 2025 +0100
Once (#20506)
* CAMEL-22431: camel-once - A component for development to trigger only once
---
bom/camel-bom/pom.xml | 5 +
catalog/camel-allcomponents/pom.xml | 5 +
.../org/apache/camel/catalog/components.properties | 1 +
.../org/apache/camel/catalog/components/once.json | 43 +++
components/camel-once/pom.xml | 54 +++
.../component/once/OnceComponentConfigurer.java | 63 +++
.../component/once/OnceEndpointConfigurer.java | 92 +++++
.../component/once/OnceEndpointUriFactory.java | 82 ++++
.../org/apache/camel/component/once/once.json | 43 +++
.../services/org/apache/camel/component.properties | 7 +
.../services/org/apache/camel/component/once | 2 +
.../org/apache/camel/configurer/once-component | 2 +
.../org/apache/camel/configurer/once-endpoint | 2 +
.../org/apache/camel/urifactory/once-endpoint | 2 +
.../camel-once/src/main/docs/once-component.adoc | 155 ++++++++
.../apache/camel/component/once/OnceComponent.java | 108 ++++++
.../apache/camel/component/once/OnceConsumer.java | 180 +++++++++
.../apache/camel/component/once/OnceEndpoint.java | 156 ++++++++
.../once/OnceBodyAndExchangePropertyTest.java | 46 +++
.../component/once/OnceBodyAndHeaderFileTest.java | 47 +++
.../component/once/OnceBodyAndHeaderTest.java | 46 +++
.../once/OnceBodyAndVariableFileTest.java | 47 +++
.../component/once/OnceBodyAndVariableTest.java | 45 +++
.../camel/component/once/OnceBodyFileTest.java | 45 +++
.../camel/component/once/OnceGroovyFileTest.java | 44 +++
.../component/once/OnceSimpleDisabledTest.java | 45 +++
.../camel/component/once/OnceSimpleFileTest.java | 44 +++
.../camel/component/once/OnceSimpleTest.java | 43 +++
.../org/apache/camel/component/once/OnceTest.java | 43 +++
.../camel-once/src/test/resources/calc.groovy | 17 +
components/camel-once/src/test/resources/data.csv | 2 +
.../camel-once/src/test/resources/letter.txt | 1 +
.../src/test/resources/log4j2.properties | 29 ++
components/camel-once/src/test/resources/price.txt | 1 +
components/pom.xml | 1 +
.../org/apache/camel/main/components.properties | 1 +
.../processor/DefaultExchangeFormatter.java | 4 +-
.../modules/ROOT/examples/json/once.json | 1 +
docs/components/modules/ROOT/nav.adoc | 1 +
.../modules/ROOT/pages/once-component.adoc | 1 +
.../component/ComponentsBuilderFactory.java | 13 +
.../component/dsl/OnceComponentBuilderFactory.java | 160 ++++++++
.../builder/endpoint/EndpointBuilderFactory.java | 1 +
.../camel/builder/endpoint/EndpointBuilders.java | 1 +
.../builder/endpoint/StaticEndpointBuilders.java | 40 ++
.../endpoint/dsl/OnceEndpointBuilderFactory.java | 427 +++++++++++++++++++++
.../camel-component-known-dependencies.properties | 1 +
.../camel-yaml-dsl/src/main/docs/yaml-dsl.adoc | 10 +-
parent/pom.xml | 5 +
49 files changed, 2209 insertions(+), 5 deletions(-)
diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml
index 643a971175b6..e399a6774f85 100644
--- a/bom/camel-bom/pom.xml
+++ b/bom/camel-bom/pom.xml
@@ -1707,6 +1707,11 @@
<artifactId>camel-olingo4-api</artifactId>
<version>4.17.0-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-once</artifactId>
+ <version>4.17.0-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-openai</artifactId>
diff --git a/catalog/camel-allcomponents/pom.xml
b/catalog/camel-allcomponents/pom.xml
index 6483ad8378df..fcbcf428b710 100644
--- a/catalog/camel-allcomponents/pom.xml
+++ b/catalog/camel-allcomponents/pom.xml
@@ -1511,6 +1511,11 @@
<artifactId>camel-olingo4-api</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-once</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-openai</artifactId>
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
index 2f97969e7b36..9cd604239c57 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
@@ -262,6 +262,7 @@ nitrite
oaipmh
olingo2
olingo4
+once
opensearch
openshift-build-configs
openshift-builds
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
new file mode 100644
index 000000000000..f1819aeb3f46
--- /dev/null
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/once.json
@@ -0,0 +1,43 @@
+{
+ "component": {
+ "kind": "component",
+ "name": "once",
+ "title": "Once",
+ "description": "Camel Once component",
+ "deprecated": false,
+ "firstVersion": "4.170.0",
+ "label": "core,scheduling",
+ "javaType": "org.apache.camel.component.once.OnceComponent",
+ "supportLevel": "Preview",
+ "groupId": "org.apache.camel",
+ "artifactId": "camel-once",
+ "version": "4.17.0-SNAPSHOT",
+ "scheme": "once",
+ "extendsScheme": "",
+ "syntax": "once:name",
+ "async": false,
+ "api": false,
+ "consumerOnly": true,
+ "producerOnly": false,
+ "lenientProperties": false,
+ "browsable": false,
+ "remote": false
+ },
+ "componentProperties": {
+ "bridgeErrorHandler": { "index": 0, "kind": "property", "displayName":
"Bridge Error Handler", "group": "consumer", "label": "consumer", "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 messages, or the like [...]
+ "autowiredEnabled": { "index": 1, "kind": "property", "displayName":
"Autowired Enabled", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": true, "description":
"Whether autowiring is enabled. This is used for automatic autowiring options
(the option must be marked as autowired) by looking up in the registry to find
if there is a single instance of matching t [...]
+ "delay": { "index": 2, "kind": "property", "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." },
+ "languages": { "index": 3, "kind": "property", "displayName": "Languages",
"group": "advanced", "label": "advanced", "required": false, "type": "boolean",
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "defaultValue": true, "description": "Whether Camel languages are
supported such as simple,groovy." }
+ },
+ "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." },
+ "headers": { "index": 2, "kind": "parameter", "displayName": "Headers",
"group": "consumer", "label": "", "required": false, "type": "object",
"javaType": "java.util.Map<java.lang.String, java.lang.String>", "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." },
+ "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." },
+ "exchangeProperties": { "index": 7, "kind": "parameter", "displayName":
"Exchange Properties", "group": "advanced", "label": "advanced", "required":
false, "type": "object", "javaType": "java.util.Map<java.lang.String,
java.lang.String>", "prefix": "exchangeProperty.", "multiValue": true,
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "supportFileReference": true, "description": "The data to use as
exchange properties as key=value pairs. You can exte [...]
+ "variables": { "index": 8, "kind": "parameter", "displayName":
"Variables", "group": "advanced", "label": "advanced", "required": false,
"type": "object", "javaType": "java.util.Map<java.lang.String,
java.lang.String>", "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/pom.xml b/components/camel-once/pom.xml
new file mode 100644
index 000000000000..33b4bd67568b
--- /dev/null
+++ b/components/camel-once/pom.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>components</artifactId>
+ <version>4.17.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>camel-once</artifactId>
+ <packaging>jar</packaging>
+
+ <name>Camel :: Once</name>
+ <description>Camel Once component</description>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-support</artifactId>
+ </dependency>
+
+ <!-- testing -->
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-junit5</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-groovy</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git
a/components/camel-once/src/generated/java/org/apache/camel/component/once/OnceComponentConfigurer.java
b/components/camel-once/src/generated/java/org/apache/camel/component/once/OnceComponentConfigurer.java
new file mode 100644
index 000000000000..50efcb4bbcbf
--- /dev/null
+++
b/components/camel-once/src/generated/java/org/apache/camel/component/once/OnceComponentConfigurer.java
@@ -0,0 +1,63 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.once;
+
+import javax.annotation.processing.Generated;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.support.component.PropertyConfigurerSupport;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.EndpointSchemaGeneratorMojo")
+@SuppressWarnings("unchecked")
+public class OnceComponentConfigurer extends PropertyConfigurerSupport
implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+ @Override
+ public boolean configure(CamelContext camelContext, Object obj, String
name, Object value, boolean ignoreCase) {
+ OnceComponent target = (OnceComponent) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "autowiredenabled":
+ case "autowiredEnabled":
target.setAutowiredEnabled(property(camelContext, boolean.class, value));
return true;
+ case "bridgeerrorhandler":
+ case "bridgeErrorHandler":
target.setBridgeErrorHandler(property(camelContext, boolean.class, value));
return true;
+ case "delay": target.setDelay(property(camelContext, long.class,
value)); return true;
+ case "languages": target.setLanguages(property(camelContext,
boolean.class, value)); return true;
+ default: return false;
+ }
+ }
+
+ @Override
+ public Class<?> getOptionType(String name, boolean ignoreCase) {
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "autowiredenabled":
+ case "autowiredEnabled": return boolean.class;
+ case "bridgeerrorhandler":
+ case "bridgeErrorHandler": return boolean.class;
+ case "delay": return long.class;
+ case "languages": return boolean.class;
+ default: return null;
+ }
+ }
+
+ @Override
+ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+ OnceComponent target = (OnceComponent) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "autowiredenabled":
+ case "autowiredEnabled": return target.isAutowiredEnabled();
+ case "bridgeerrorhandler":
+ case "bridgeErrorHandler": return target.isBridgeErrorHandler();
+ case "delay": return target.getDelay();
+ case "languages": return target.isLanguages();
+ default: return null;
+ }
+ }
+}
+
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
new file mode 100644
index 000000000000..89d0af57d099
--- /dev/null
+++
b/components/camel-once/src/generated/java/org/apache/camel/component/once/OnceEndpointConfigurer.java
@@ -0,0 +1,92 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.once;
+
+import javax.annotation.processing.Generated;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.support.component.PropertyConfigurerSupport;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.EndpointSchemaGeneratorMojo")
+@SuppressWarnings("unchecked")
+public class OnceEndpointConfigurer extends PropertyConfigurerSupport
implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+ @Override
+ public boolean configure(CamelContext camelContext, Object obj, String
name, Object value, boolean ignoreCase) {
+ OnceEndpoint target = (OnceEndpoint) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "body": target.setBody(property(camelContext,
java.lang.String.class, value)); return true;
+ case "bridgeerrorhandler":
+ case "bridgeErrorHandler":
target.setBridgeErrorHandler(property(camelContext, boolean.class, value));
return true;
+ case "delay": target.setDelay(property(camelContext, long.class,
value)); return true;
+ case "exceptionhandler":
+ 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 "exchangeproperties":
+ case "exchangeProperties":
target.setExchangeProperties(property(camelContext, java.util.Map.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;
+ }
+ }
+
+ @Override
+ public Class<?> getOptionType(String name, boolean ignoreCase) {
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "body": return java.lang.String.class;
+ case "bridgeerrorhandler":
+ case "bridgeErrorHandler": return boolean.class;
+ case "delay": return long.class;
+ case "exceptionhandler":
+ case "exceptionHandler": return
org.apache.camel.spi.ExceptionHandler.class;
+ case "exchangepattern":
+ case "exchangePattern": return org.apache.camel.ExchangePattern.class;
+ case "exchangeproperties":
+ case "exchangeProperties": return java.util.Map.class;
+ case "headers": return java.util.Map.class;
+ case "variables": return java.util.Map.class;
+ default: return null;
+ }
+ }
+
+ @Override
+ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+ OnceEndpoint target = (OnceEndpoint) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "body": return target.getBody();
+ case "bridgeerrorhandler":
+ case "bridgeErrorHandler": return target.isBridgeErrorHandler();
+ case "delay": return target.getDelay();
+ case "exceptionhandler":
+ case "exceptionHandler": return target.getExceptionHandler();
+ case "exchangepattern":
+ case "exchangePattern": return target.getExchangePattern();
+ case "exchangeproperties":
+ case "exchangeProperties": return target.getExchangeProperties();
+ 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 "exchangeproperties":
+ case "exchangeProperties": return java.lang.String.class;
+ case "headers": return java.lang.String.class;
+ case "variables": return java.lang.String.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
new file mode 100644
index 000000000000..6a56d6639ef9
--- /dev/null
+++
b/components/camel-once/src/generated/java/org/apache/camel/component/once/OnceEndpointUriFactory.java
@@ -0,0 +1,82 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.once;
+
+import javax.annotation.processing.Generated;
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.spi.EndpointUriFactory;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.GenerateEndpointUriFactoryMojo")
+public class OnceEndpointUriFactory extends
org.apache.camel.support.component.EndpointUriFactorySupport implements
EndpointUriFactory {
+
+ private static final String BASE = ":name";
+
+ private static final Set<String> PROPERTY_NAMES;
+ private static final Set<String> SECRET_PROPERTY_NAMES;
+ private static final Map<String, String> MULTI_VALUE_PREFIXES;
+ static {
+ Set<String> props = new HashSet<>(9);
+ props.add("body");
+ props.add("bridgeErrorHandler");
+ props.add("delay");
+ props.add("exceptionHandler");
+ props.add("exchangePattern");
+ props.add("exchangeProperties");
+ props.add("headers");
+ props.add("name");
+ props.add("variables");
+ PROPERTY_NAMES = Collections.unmodifiableSet(props);
+ SECRET_PROPERTY_NAMES = Collections.emptySet();
+ Map<String, String> prefixes = new HashMap<>(3);
+ prefixes.put("exchangeProperties", "exchangeProperty.");
+ prefixes.put("headers", "header.");
+ prefixes.put("variables", "variable.");
+ MULTI_VALUE_PREFIXES = Collections.unmodifiableMap(prefixes);
+ }
+
+ @Override
+ public boolean isEnabled(String scheme) {
+ return "once".equals(scheme);
+ }
+
+ @Override
+ public String buildUri(String scheme, Map<String, Object> properties,
boolean encode) throws URISyntaxException {
+ String syntax = scheme + BASE;
+ String uri = syntax;
+
+ Map<String, Object> copy = new HashMap<>(properties);
+
+ uri = buildPathParameter(syntax, uri, "name", null, true, copy);
+ uri = buildQueryParameters(uri, copy, encode);
+ return uri;
+ }
+
+ @Override
+ public Set<String> propertyNames() {
+ return PROPERTY_NAMES;
+ }
+
+ @Override
+ public Set<String> secretPropertyNames() {
+ return SECRET_PROPERTY_NAMES;
+ }
+
+ @Override
+ public Map<String, String> multiValuePrefixes() {
+ return MULTI_VALUE_PREFIXES;
+ }
+
+ @Override
+ public boolean isLenientProperties() {
+ return false;
+ }
+}
+
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
new file mode 100644
index 000000000000..f1819aeb3f46
--- /dev/null
+++
b/components/camel-once/src/generated/resources/META-INF/org/apache/camel/component/once/once.json
@@ -0,0 +1,43 @@
+{
+ "component": {
+ "kind": "component",
+ "name": "once",
+ "title": "Once",
+ "description": "Camel Once component",
+ "deprecated": false,
+ "firstVersion": "4.170.0",
+ "label": "core,scheduling",
+ "javaType": "org.apache.camel.component.once.OnceComponent",
+ "supportLevel": "Preview",
+ "groupId": "org.apache.camel",
+ "artifactId": "camel-once",
+ "version": "4.17.0-SNAPSHOT",
+ "scheme": "once",
+ "extendsScheme": "",
+ "syntax": "once:name",
+ "async": false,
+ "api": false,
+ "consumerOnly": true,
+ "producerOnly": false,
+ "lenientProperties": false,
+ "browsable": false,
+ "remote": false
+ },
+ "componentProperties": {
+ "bridgeErrorHandler": { "index": 0, "kind": "property", "displayName":
"Bridge Error Handler", "group": "consumer", "label": "consumer", "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 messages, or the like [...]
+ "autowiredEnabled": { "index": 1, "kind": "property", "displayName":
"Autowired Enabled", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": true, "description":
"Whether autowiring is enabled. This is used for automatic autowiring options
(the option must be marked as autowired) by looking up in the registry to find
if there is a single instance of matching t [...]
+ "delay": { "index": 2, "kind": "property", "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." },
+ "languages": { "index": 3, "kind": "property", "displayName": "Languages",
"group": "advanced", "label": "advanced", "required": false, "type": "boolean",
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "defaultValue": true, "description": "Whether Camel languages are
supported such as simple,groovy." }
+ },
+ "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." },
+ "headers": { "index": 2, "kind": "parameter", "displayName": "Headers",
"group": "consumer", "label": "", "required": false, "type": "object",
"javaType": "java.util.Map<java.lang.String, java.lang.String>", "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." },
+ "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." },
+ "exchangeProperties": { "index": 7, "kind": "parameter", "displayName":
"Exchange Properties", "group": "advanced", "label": "advanced", "required":
false, "type": "object", "javaType": "java.util.Map<java.lang.String,
java.lang.String>", "prefix": "exchangeProperty.", "multiValue": true,
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "supportFileReference": true, "description": "The data to use as
exchange properties as key=value pairs. You can exte [...]
+ "variables": { "index": 8, "kind": "parameter", "displayName":
"Variables", "group": "advanced", "label": "advanced", "required": false,
"type": "object", "javaType": "java.util.Map<java.lang.String,
java.lang.String>", "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/resources/META-INF/services/org/apache/camel/component.properties
b/components/camel-once/src/generated/resources/META-INF/services/org/apache/camel/component.properties
new file mode 100644
index 000000000000..5ce57a5274c5
--- /dev/null
+++
b/components/camel-once/src/generated/resources/META-INF/services/org/apache/camel/component.properties
@@ -0,0 +1,7 @@
+# Generated by camel build tools - do NOT edit this file!
+components=once
+groupId=org.apache.camel
+artifactId=camel-once
+version=4.17.0-SNAPSHOT
+projectName=Camel :: Once
+projectDescription=Camel Once component
diff --git
a/components/camel-once/src/generated/resources/META-INF/services/org/apache/camel/component/once
b/components/camel-once/src/generated/resources/META-INF/services/org/apache/camel/component/once
new file mode 100644
index 000000000000..6f617d1f96cf
--- /dev/null
+++
b/components/camel-once/src/generated/resources/META-INF/services/org/apache/camel/component/once
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.once.OnceComponent
diff --git
a/components/camel-once/src/generated/resources/META-INF/services/org/apache/camel/configurer/once-component
b/components/camel-once/src/generated/resources/META-INF/services/org/apache/camel/configurer/once-component
new file mode 100644
index 000000000000..76dec0b84023
--- /dev/null
+++
b/components/camel-once/src/generated/resources/META-INF/services/org/apache/camel/configurer/once-component
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.once.OnceComponentConfigurer
diff --git
a/components/camel-once/src/generated/resources/META-INF/services/org/apache/camel/configurer/once-endpoint
b/components/camel-once/src/generated/resources/META-INF/services/org/apache/camel/configurer/once-endpoint
new file mode 100644
index 000000000000..8089f8f8cde8
--- /dev/null
+++
b/components/camel-once/src/generated/resources/META-INF/services/org/apache/camel/configurer/once-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.once.OnceEndpointConfigurer
diff --git
a/components/camel-once/src/generated/resources/META-INF/services/org/apache/camel/urifactory/once-endpoint
b/components/camel-once/src/generated/resources/META-INF/services/org/apache/camel/urifactory/once-endpoint
new file mode 100644
index 000000000000..ffe0e5da1c93
--- /dev/null
+++
b/components/camel-once/src/generated/resources/META-INF/services/org/apache/camel/urifactory/once-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.once.OnceEndpointUriFactory
diff --git a/components/camel-once/src/main/docs/once-component.adoc
b/components/camel-once/src/main/docs/once-component.adoc
new file mode 100644
index 000000000000..01d8c09bd9e8
--- /dev/null
+++ b/components/camel-once/src/main/docs/once-component.adoc
@@ -0,0 +1,155 @@
+= Once Component
+:doctitle: Once
+:shortname: once
+:artifactid: camel-once
+:description: Camel Once component
+:since: 4.170
+:supportlevel: Preview
+:tabs-sync-option:
+:component-header: Only consumer is supported
+:core:
+//Manually maintained attributes
+:camel-spring-boot-name: once
+
+*Since Camel {since}*
+
+*{component-header}*
+
+The Once component is used to generate a message only once. For example to
trigger a message after Camel has been started,
+or for development and testing purposes.
+
+This component is designed to be very basic and only a few options.
+
+You can find more features when using the xref:timer-component.adoc[Timer]
component,
+which also can be configured to only trigger once with `repeatCount=1`.
+
+== URI format
+
+----
+once:name[?options]
+----
+
+Where `name` is a logical name.
+
+// component options: START
+include::partial$component-configure-options.adoc[]
+include::partial$component-endpoint-options.adoc[]
+include::partial$component-endpoint-headers.adoc[]
+// component options: END
+
+
+== Usage
+
+== Example
+
+To set up a route that generates an event every 60 seconds:
+
+[source,java]
+----
+from("once:foo?body=file:data.json").to("bean:myBean?method=someMethodName");
+----
+
+The above route will trigger once and load the `data.json` from file system
and use as message body.
+And then route to call the bean.
+
+And the route in XML DSL:
+
+[source,xml]
+-----
+<route>
+ <from uri="once:foo?body=file:data.json"/>
+ <to uri="bean:myBean?method=someMethodName"/>
+</route>
+-----
+
+=== Using headers and variables
+
+You can also specify headers and variables using _multivalue_, where each
header is prefixed with `header.<key>`.
+In the sample below we set 2 headers as follows: `foo=abc` and `bar=123`.
+
+[source,java]
+----
+from("once:tick?body=world&header.foo=abc&header.bar=123")
+ .to("bean:myBean");
+----
+
+You can do the same for variables with `variable.<key>`.
+
+And in YAML DSL you can use YAML map's directly as shown below:
+
+[source,yaml]
+----
+- route:
+ from:
+ uri: once
+ parameters:
+ name: hello
+ body: Hello World
+ headers:
+ foo: foolish
+ bar: 456
+ steps:
+ - to: mock:result
+----
+
+IMPORTANT: This requires that the `uri` does not have any configuration so it
must be `uri: once` and not `uri: once:hello`.
+
+=== Using custom languages
+
+You can use the Camel languages such as simple, or groovy when specifying
body, headers, exchange properties, and variables.
+
+The once component will set the data in the following order:
+
+- variables
+- exchangeProperties
+- headers
+- body
+
+This makes it possible to use groovy or simple language for setting the
message body, based
+on data from the variables and headers.
+
+For example:
+
+[source,java]
+----
+from("once:tick?body=language:groovy:file:src/test/resources/calc.groovy&variable.amount=123")
+ .to("mock:result");
+----
+
+You must use `language:groovy:` as prefix when using languages. And you can
combine this with loading from file.
+The `calc.groovy` file is as follows:
+
+[source,groovy]
+----
+variable.amount * 3
+----
+
+As you can see this just tells groovy to multiply the amount variable with 3.
+
+=== Automatic type conversion
+
+The body, header, and variables will automatically be converted to the best
suitable type for boolean and integers:
+
+- boolean
+- int
+- long
+
+And for any other its `String` or the output from executing a language.
+
+=== Firing as soon as possible
+
+By default, the component is fired after 1 seconds when Camel has been fully
started.
+If you want to fire messages in a Camel route as soon as possible, you can use
a negative delay:
+
+[source,xml]
+----
+<route>
+ <from uri="once:foo?body=file.data.json&delay=-1"/>
+ <to uri="bean:myBean?method=someMethodName"/>
+</route>
+----
+
+In this way, the timer will fire messages immediately.
+
+
+include::spring-boot:partial$starter.adoc[]
diff --git
a/components/camel-once/src/main/java/org/apache/camel/component/once/OnceComponent.java
b/components/camel-once/src/main/java/org/apache/camel/component/once/OnceComponent.java
new file mode 100644
index 000000000000..e9752f99650e
--- /dev/null
+++
b/components/camel-once/src/main/java/org/apache/camel/component/once/OnceComponent.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.once;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.annotations.Component;
+import org.apache.camel.support.DefaultComponent;
+import org.apache.camel.util.PropertiesHelper;
+
+@Component("once")
+public class OnceComponent extends DefaultComponent {
+
+ @Metadata(label = "advanced", defaultValue = "1000")
+ private long delay = 1000;
+
+ @Metadata(label = "advanced", defaultValue = "true")
+ private boolean languages = true;
+
+ @Override
+ protected Endpoint createEndpoint(String uri, String remaining,
Map<String, Object> parameters) throws Exception {
+ OnceEndpoint answer = new OnceEndpoint(uri, this, remaining);
+ answer.setDelay(delay);
+
+ Map<String, String> headers =
getAndRemoveOrResolveReferenceParameter(parameters, "headers", Map.class);
+ Map<String, Object> map =
PropertiesHelper.extractProperties(parameters, "header.");
+ if (map != null && !map.isEmpty()) {
+ if (headers == null) {
+ headers = new LinkedHashMap<>();
+ }
+ for (Map.Entry<String, Object> me : map.entrySet()) {
+ headers.put(me.getKey(), me.getValue().toString());
+ }
+ }
+ if (headers != null && !headers.isEmpty()) {
+ answer.setHeaders(headers);
+ }
+ Map<String, String> variables =
getAndRemoveOrResolveReferenceParameter(parameters, "variables", Map.class);
+ map = PropertiesHelper.extractProperties(parameters, "variable.");
+ if (map != null && !map.isEmpty()) {
+ if (variables == null) {
+ variables = new LinkedHashMap<>();
+ }
+ for (Map.Entry<String, Object> me : map.entrySet()) {
+ variables.put(me.getKey(), me.getValue().toString());
+ }
+ }
+ if (variables != null && !variables.isEmpty()) {
+ answer.setVariables(variables);
+ }
+ Map<String, String> properties =
getAndRemoveOrResolveReferenceParameter(parameters, "exchangeProperties",
Map.class);
+ map = PropertiesHelper.extractProperties(parameters,
"exchangeProperty.");
+ if (map != null && !map.isEmpty()) {
+ if (properties == null) {
+ properties = new LinkedHashMap<>();
+ }
+ for (Map.Entry<String, Object> me : map.entrySet()) {
+ properties.put(me.getKey(), me.getValue().toString());
+ }
+ }
+ if (properties != null && !properties.isEmpty()) {
+ answer.setExchangeProperties(properties);
+ }
+ setProperties(answer, parameters);
+ return answer;
+ }
+
+ public long getDelay() {
+ return delay;
+ }
+
+ /**
+ * The number of milliseconds to wait before triggering.
+ * <p/>
+ * The default value is 1000.
+ */
+ public void setDelay(long delay) {
+ this.delay = delay;
+ }
+
+ public boolean isLanguages() {
+ return languages;
+ }
+
+ /**
+ * Whether Camel languages are supported such as simple,groovy.
+ */
+ public void setLanguages(boolean languages) {
+ this.languages = languages;
+ }
+}
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
new file mode 100644
index 000000000000..c4d29d7d8eaf
--- /dev/null
+++
b/components/camel-once/src/main/java/org/apache/camel/component/once/OnceConsumer.java
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.once;
+
+import java.io.InputStream;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.NoSuchLanguageException;
+import org.apache.camel.Processor;
+import org.apache.camel.StartupListener;
+import org.apache.camel.spi.Language;
+import org.apache.camel.support.DefaultConsumer;
+import org.apache.camel.support.ResourceHelper;
+import org.apache.camel.util.StringHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OnceConsumer extends DefaultConsumer implements StartupListener {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(OnceConsumer.class);
+
+ private final CamelContext camelContext;
+ private final OnceEndpoint endpoint;
+ private final Timer timer;
+ private final TimerTask task;
+ private volatile boolean scheduled;
+
+ public OnceConsumer(OnceEndpoint endpoint, Processor processor) {
+ super(endpoint, processor);
+ this.camelContext = endpoint.getCamelContext();
+ this.endpoint = endpoint;
+ this.timer = new Timer(endpoint.getName());
+ this.task = new OnceTimerTask();
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ super.doStart();
+ if (!scheduled && endpoint.getCamelContext().getStatus().isStarted()) {
+ scheduleTask(task, timer);
+ }
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ if (task != null) {
+ task.cancel();
+ }
+ scheduled = false;
+ super.doStop();
+ }
+
+ @Override
+ public void onCamelContextStarted(CamelContext context, boolean
alreadyStarted) throws Exception {
+ if (!scheduled) {
+ scheduleTask(task, timer);
+ }
+ }
+
+ protected void scheduleTask(TimerTask task, Timer timer) {
+ long delay = Math.max(0, endpoint.getDelay());
+ LOG.debug("Scheduled once after: {} mills for task: {} ", delay, task);
+ timer.schedule(task, delay);
+ scheduled = true;
+ }
+
+ private class OnceTimerTask extends TimerTask {
+
+ @Override
+ public void run() {
+ Exchange exchange = createExchange(false);
+ try {
+ // variables,properties,headers,and body last
+ if (endpoint.getVariables() != null) {
+ for (var e : endpoint.getVariables().entrySet()) {
+ Object v = resolveData(exchange, e.getValue());
+ if (v != null) {
+ exchange.setVariable(e.getKey(), v);
+ }
+ }
+ }
+ if (endpoint.getExchangeProperties() != null) {
+ for (var e : endpoint.getExchangeProperties().entrySet()) {
+ Object v = resolveData(exchange, e.getValue());
+ if (v != null) {
+ exchange.setProperty(e.getKey(), v);
+ }
+ }
+ }
+ if (endpoint.getHeaders() != null) {
+ for (var e : endpoint.getHeaders().entrySet()) {
+ Object v = resolveData(exchange, e.getValue());
+ if (v != null) {
+ exchange.getMessage().setHeader(e.getKey(), v);
+ }
+ }
+ }
+ Object body = resolveData(exchange, endpoint.getBody());
+ exchange.getMessage().setBody(body);
+ getProcessor().process(exchange);
+ } catch (Exception e) {
+ exchange.setException(e);
+ }
+
+ // handle any thrown exception
+ try {
+ if (exchange.getException() != null) {
+ getExceptionHandler().handleException("Error processing
exchange", exchange, exchange.getException());
+ }
+ } finally {
+ releaseExchange(exchange, false);
+ }
+ }
+ }
+
+ private Object resolveData(Exchange exchange, Object data) throws
Exception {
+ String answer = data instanceof String ? data.toString() : null;
+
+ // if languages is supported then you can prefix with simple:xxx or
groovy:xxx to let Camel know
+ Language lan = null;
+ if (answer != null && endpoint.getComponent().isLanguages() &&
answer.startsWith("language:")) {
+ String text = answer.substring(9);
+ String prefix = StringHelper.before(text, ":");
+ if (prefix != null) {
+ try {
+ lan = camelContext.resolveLanguage(prefix);
+ answer = StringHelper.after(text, ":");
+ } catch (NoSuchLanguageException e) {
+ // ignore it's not a language
+ }
+ }
+ }
+
+ if (ResourceHelper.hasScheme(answer)) {
+ try (InputStream is =
ResourceHelper.resolveMandatoryResourceAsInputStream(camelContext, answer)) {
+ answer =
camelContext.getTypeConverter().mandatoryConvertTo(String.class, is);
+ }
+ }
+
+ if (answer != null && lan != null) {
+ return lan.createExpression(answer).evaluate(exchange,
Object.class);
+ }
+
+ // data may be boolean, integer, or literal
+ if ("true".equalsIgnoreCase(answer)) {
+ return true;
+ } else if ("false".equalsIgnoreCase(answer)) {
+ return false;
+ } else {
+ Object val =
camelContext.getTypeConverter().tryConvertTo(Integer.class, exchange, data);
+ if (val != null) {
+ return val;
+ }
+ val = camelContext.getTypeConverter().tryConvertTo(Long.class,
exchange, data);
+ if (val != null) {
+ return val;
+ }
+ }
+
+ return answer;
+ }
+
+}
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
new file mode 100644
index 000000000000..117d89cf683c
--- /dev/null
+++
b/components/camel-once/src/main/java/org/apache/camel/component/once/OnceEndpoint.java
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.once;
+
+import java.util.Map;
+
+import org.apache.camel.Category;
+import org.apache.camel.Component;
+import org.apache.camel.Consumer;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriPath;
+import org.apache.camel.support.DefaultEndpoint;
+
+@UriEndpoint(firstVersion = "4.170.0", scheme = "once", title = "Once", syntax
= "once:name", consumerOnly = true,
+ remote = false, category = { Category.CORE, Category.SCHEDULING })
+public class OnceEndpoint extends DefaultEndpoint {
+
+ @UriPath
+ @Metadata(required = true)
+ private String name;
+ @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, String> headers;
+ @UriParam(label = "advanced", multiValue = true, prefix = "variable.")
+ @Metadata(supportFileReference = true)
+ private Map<String, String> variables;
+ @UriParam(label = "advanced", multiValue = true, prefix =
"exchangeProperty.")
+ @Metadata(supportFileReference = true)
+ private Map<String, String> exchangeProperties;
+
+ public OnceEndpoint() {
+ }
+
+ public OnceEndpoint(String endpointUri, Component component, String name) {
+ super(endpointUri, component);
+ this.name = name;
+ }
+
+ @Override
+ public boolean isRemote() {
+ return false;
+ }
+
+ @Override
+ public OnceComponent getComponent() {
+ return (OnceComponent) super.getComponent();
+ }
+
+ @Override
+ public Producer createProducer() throws Exception {
+ throw new RuntimeCamelException("Cannot produce to a OnceEndpoint: " +
getEndpointUri());
+ }
+
+ @Override
+ public Consumer createConsumer(Processor processor) throws Exception {
+ Consumer answer = new OnceConsumer(this, processor);
+ configureConsumer(answer);
+ return answer;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * The logical name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public long getDelay() {
+ return delay;
+ }
+
+ /**
+ * The number of milliseconds to wait before triggering.
+ * <p/>
+ * The default value is 1000.
+ */
+ public void setDelay(long delay) {
+ this.delay = delay;
+ }
+
+ public String getBody() {
+ return body;
+ }
+
+ /**
+ * 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.
+ */
+ 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, String> getHeaders() {
+ return headers;
+ }
+
+ public void setHeaders(Map<String, String> headers) {
+ this.headers = headers;
+ }
+
+ public Map<String, String> 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, String> variables) {
+ this.variables = variables;
+ }
+
+ public Map<String, String> getExchangeProperties() {
+ return exchangeProperties;
+ }
+
+ /**
+ * The data to use as exchange properties 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 setExchangeProperties(Map<String, String> exchangeProperties) {
+ this.exchangeProperties = exchangeProperties;
+ }
+}
diff --git
a/components/camel-once/src/test/java/org/apache/camel/component/once/OnceBodyAndExchangePropertyTest.java
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceBodyAndExchangePropertyTest.java
new file mode 100644
index 000000000000..8a0fbd3b68a5
--- /dev/null
+++
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceBodyAndExchangePropertyTest.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.once;
+
+import org.apache.camel.Exchange;
+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 OnceBodyAndExchangePropertyTest extends CamelTestSupport {
+
+ @Test
+ public void testOnce() throws Exception {
+ getMockEndpoint("mock:result").expectedBodiesReceived("world");
+ getMockEndpoint("mock:result").expectedHeaderReceived("foo", "abc");
+
getMockEndpoint("mock:result").expectedPropertyReceived(Exchange.CONTENT_TYPE,
"text/plain");
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("once:tick?delay=-1&body=world&header.foo=abc&exchangeProperty.Content-Type=text/plain").to("mock:result");
+ }
+ };
+ }
+}
diff --git
a/components/camel-once/src/test/java/org/apache/camel/component/once/OnceBodyAndHeaderFileTest.java
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceBodyAndHeaderFileTest.java
new file mode 100644
index 000000000000..c666487a0f1c
--- /dev/null
+++
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceBodyAndHeaderFileTest.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.once;
+
+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 OnceBodyAndHeaderFileTest extends CamelTestSupport {
+
+ @Test
+ public void testOnce() throws Exception {
+ getMockEndpoint("mock:result").expectedBodiesReceived("1,jack",
"2,moe");
+ getMockEndpoint("mock:result").expectedHeaderReceived("foo", "abc");
+ getMockEndpoint("mock:result").expectedHeaderReceived("bar", 456);
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("once:tick?delay=-1&body=file:src/test/resources/data.csv&header.foo=abc&header.bar=classpath:price.txt")
+ .split(body().tokenize("\n"))
+ .to("mock:result");
+ }
+ };
+ }
+}
diff --git
a/components/camel-once/src/test/java/org/apache/camel/component/once/OnceBodyAndHeaderTest.java
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceBodyAndHeaderTest.java
new file mode 100644
index 000000000000..a2f02681dc9d
--- /dev/null
+++
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceBodyAndHeaderTest.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.once;
+
+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 OnceBodyAndHeaderTest extends CamelTestSupport {
+
+ @Test
+ public void testOnce() throws Exception {
+ getMockEndpoint("mock:result").expectedBodiesReceived("world");
+ getMockEndpoint("mock:result").expectedHeaderReceived("foo", "abc");
+ getMockEndpoint("mock:result").expectedHeaderReceived("bar", 123);
+ getMockEndpoint("mock:result").expectedHeaderReceived("priority",
true);
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("once:tick?delay=-1&body=world&header.foo=abc&header.bar=123&header.priority=true").to("mock:result");
+ }
+ };
+ }
+}
diff --git
a/components/camel-once/src/test/java/org/apache/camel/component/once/OnceBodyAndVariableFileTest.java
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceBodyAndVariableFileTest.java
new file mode 100644
index 000000000000..7f244cf122fd
--- /dev/null
+++
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceBodyAndVariableFileTest.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.once;
+
+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 OnceBodyAndVariableFileTest extends CamelTestSupport {
+
+ @Test
+ public void testOnce() throws Exception {
+ getMockEndpoint("mock:result").expectedBodiesReceived("1,jack",
"2,moe");
+ getMockEndpoint("mock:result").expectedHeaderReceived("foo", "abc");
+ getMockEndpoint("mock:result").expectedVariableReceived("bar", 456);
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("once:tick?delay=-1&body=file:src/test/resources/data.csv&header.foo=abc&variable.bar=classpath:price.txt")
+ .split(body().tokenize("\n"))
+ .to("mock:result");
+ }
+ };
+ }
+}
diff --git
a/components/camel-once/src/test/java/org/apache/camel/component/once/OnceBodyAndVariableTest.java
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceBodyAndVariableTest.java
new file mode 100644
index 000000000000..18eb26f7ff78
--- /dev/null
+++
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceBodyAndVariableTest.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.once;
+
+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 OnceBodyAndVariableTest extends CamelTestSupport {
+
+ @Test
+ public void testOnce() throws Exception {
+ getMockEndpoint("mock:result").expectedBodiesReceived("world");
+ getMockEndpoint("mock:result").expectedHeaderReceived("foo", "abc");
+ getMockEndpoint("mock:result").expectedVariableReceived("bar", 123);
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("once:tick?delay=-1&body=world&header.foo=abc&variable.bar=123").to("mock:result");
+ }
+ };
+ }
+}
diff --git
a/components/camel-once/src/test/java/org/apache/camel/component/once/OnceBodyFileTest.java
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceBodyFileTest.java
new file mode 100644
index 000000000000..f5751c102d0b
--- /dev/null
+++
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceBodyFileTest.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.once;
+
+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 OnceBodyFileTest extends CamelTestSupport {
+
+ @Test
+ public void testOnce() throws Exception {
+ getMockEndpoint("mock:result").expectedBodiesReceived("1,jack",
"2,moe");
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("once:tick?delay=-1&body=file:src/test/resources/data.csv")
+ .split(body().tokenize("\n"))
+ .to("mock:result");
+ }
+ };
+ }
+}
diff --git
a/components/camel-once/src/test/java/org/apache/camel/component/once/OnceGroovyFileTest.java
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceGroovyFileTest.java
new file mode 100644
index 000000000000..5af24e45eaf7
--- /dev/null
+++
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceGroovyFileTest.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.once;
+
+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 OnceGroovyFileTest extends CamelTestSupport {
+
+ @Test
+ public void testOnce() throws Exception {
+ getMockEndpoint("mock:result").expectedBodiesReceived(369);
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("once:tick?delay=-1&body=language:groovy:file:src/test/resources/calc.groovy&variable.amount=123")
+ .to("mock:result");
+ }
+ };
+ }
+}
diff --git
a/components/camel-once/src/test/java/org/apache/camel/component/once/OnceSimpleDisabledTest.java
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceSimpleDisabledTest.java
new file mode 100644
index 000000000000..4a41355d0527
--- /dev/null
+++
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceSimpleDisabledTest.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.once;
+
+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 OnceSimpleDisabledTest extends CamelTestSupport {
+
+ @Test
+ public void testOnce() throws Exception {
+
getMockEndpoint("mock:result").expectedBodiesReceived("language:simple:${camelId}");
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ context.getComponent("once",
OnceComponent.class).setLanguages(false);
+
+
from("once:tick?delay=-1&body=language:simple:${camelId}").to("mock:result");
+ }
+ };
+ }
+}
diff --git
a/components/camel-once/src/test/java/org/apache/camel/component/once/OnceSimpleFileTest.java
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceSimpleFileTest.java
new file mode 100644
index 000000000000..6765d899f450
--- /dev/null
+++
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceSimpleFileTest.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.once;
+
+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 OnceSimpleFileTest extends CamelTestSupport {
+
+ @Test
+ public void testOnce() throws Exception {
+ getMockEndpoint("mock:result")
+ .expectedBodiesReceived("Hello this is " + context.getName() +
" from " + context.getRoutes().get(0).getId());
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("once:tick?delay=-1&body=language:simple:file:src/test/resources/letter.txt").to("mock:result");
+ }
+ };
+ }
+}
diff --git
a/components/camel-once/src/test/java/org/apache/camel/component/once/OnceSimpleTest.java
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceSimpleTest.java
new file mode 100644
index 000000000000..d0748db259e2
--- /dev/null
+++
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceSimpleTest.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.once;
+
+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 OnceSimpleTest extends CamelTestSupport {
+
+ @Test
+ public void testOnce() throws Exception {
+
getMockEndpoint("mock:result").expectedBodiesReceived(context.getName());
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
from("once:tick?delay=-1&body=language:simple:${camelId}").to("mock:result");
+ }
+ };
+ }
+}
diff --git
a/components/camel-once/src/test/java/org/apache/camel/component/once/OnceTest.java
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceTest.java
new file mode 100644
index 000000000000..296b18f41559
--- /dev/null
+++
b/components/camel-once/src/test/java/org/apache/camel/component/once/OnceTest.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.once;
+
+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 OnceTest extends CamelTestSupport {
+
+ @Test
+ public void testOnce() throws Exception {
+ getMockEndpoint("mock:result").expectedBodiesReceived("hello");
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("once:tick?body=hello").to("mock:result");
+ }
+ };
+ }
+}
diff --git a/components/camel-once/src/test/resources/calc.groovy
b/components/camel-once/src/test/resources/calc.groovy
new file mode 100644
index 000000000000..3490ed55237a
--- /dev/null
+++ b/components/camel-once/src/test/resources/calc.groovy
@@ -0,0 +1,17 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+variable.amount * 3
\ No newline at end of file
diff --git a/components/camel-once/src/test/resources/data.csv
b/components/camel-once/src/test/resources/data.csv
new file mode 100644
index 000000000000..6554140f0c5d
--- /dev/null
+++ b/components/camel-once/src/test/resources/data.csv
@@ -0,0 +1,2 @@
+1,jack
+2,moe
\ No newline at end of file
diff --git a/components/camel-once/src/test/resources/letter.txt
b/components/camel-once/src/test/resources/letter.txt
new file mode 100644
index 000000000000..daf706dfdacf
--- /dev/null
+++ b/components/camel-once/src/test/resources/letter.txt
@@ -0,0 +1 @@
+Hello this is ${camelId} from ${routeId}
\ No newline at end of file
diff --git a/components/camel-once/src/test/resources/log4j2.properties
b/components/camel-once/src/test/resources/log4j2.properties
new file mode 100644
index 000000000000..3e730b946a76
--- /dev/null
+++ b/components/camel-once/src/test/resources/log4j2.properties
@@ -0,0 +1,29 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements. See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-once-test.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+appender.out.type = Console
+appender.out.name = out
+appender.out.layout.type = PatternLayout
+appender.out.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+
+rootLogger.level = INFO
+rootLogger.appenderRef.file.ref = file
diff --git a/components/camel-once/src/test/resources/price.txt
b/components/camel-once/src/test/resources/price.txt
new file mode 100644
index 000000000000..ee2b8364542e
--- /dev/null
+++ b/components/camel-once/src/test/resources/price.txt
@@ -0,0 +1 @@
+456
\ No newline at end of file
diff --git a/components/pom.xml b/components/pom.xml
index 8e01ba1b9f14..d94d234c7ebc 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -242,6 +242,7 @@
<module>camel-ognl</module>
<module>camel-olingo2</module>
<module>camel-olingo4</module>
+ <module>camel-once</module>
<module>camel-openstack</module>
<module>camel-opentelemetry</module>
<module>camel-opentelemetry2</module>
diff --git
a/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties
b/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties
index 2f97969e7b36..9cd604239c57 100644
---
a/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties
+++
b/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties
@@ -262,6 +262,7 @@ nitrite
oaipmh
olingo2
olingo4
+once
opensearch
openshift-build-configs
openshift-builds
diff --git
a/core/camel-support/src/main/java/org/apache/camel/support/processor/DefaultExchangeFormatter.java
b/core/camel-support/src/main/java/org/apache/camel/support/processor/DefaultExchangeFormatter.java
index 15ef56013a0d..9ac3638c0d0a 100644
---
a/core/camel-support/src/main/java/org/apache/camel/support/processor/DefaultExchangeFormatter.java
+++
b/core/camel-support/src/main/java/org/apache/camel/support/processor/DefaultExchangeFormatter.java
@@ -149,7 +149,9 @@ public class DefaultExchangeFormatter implements
ExchangeFormatter {
if (route != null) {
group = route.getGroup();
}
- style(sb, "RouteGroup").append(group);
+ if (group != null) {
+ style(sb, "RouteGroup").append(group);
+ }
}
if (showAll || showRouteId) {
if (multiline) {
diff --git a/docs/components/modules/ROOT/examples/json/once.json
b/docs/components/modules/ROOT/examples/json/once.json
new file mode 120000
index 000000000000..a562c68acbc7
--- /dev/null
+++ b/docs/components/modules/ROOT/examples/json/once.json
@@ -0,0 +1 @@
+../../../../../../components/camel-once/src/generated/resources/META-INF/org/apache/camel/component/once/once.json
\ No newline at end of file
diff --git a/docs/components/modules/ROOT/nav.adoc
b/docs/components/modules/ROOT/nav.adoc
index f5a7e7914716..9823bd3db03c 100644
--- a/docs/components/modules/ROOT/nav.adoc
+++ b/docs/components/modules/ROOT/nav.adoc
@@ -280,6 +280,7 @@
** xref:oaipmh-component.adoc[OAI-PMH]
** xref:olingo2-component.adoc[Olingo2]
** xref:olingo4-component.adoc[Olingo4]
+** xref:once-component.adoc[Once]
** xref:milo-browse-component.adoc[OPC UA Browser]
** xref:milo-client-component.adoc[OPC UA Client]
** xref:milo-server-component.adoc[OPC UA Server]
diff --git a/docs/components/modules/ROOT/pages/once-component.adoc
b/docs/components/modules/ROOT/pages/once-component.adoc
new file mode 120000
index 000000000000..63187382584d
--- /dev/null
+++ b/docs/components/modules/ROOT/pages/once-component.adoc
@@ -0,0 +1 @@
+../../../../../components/camel-once/src/main/docs/once-component.adoc
\ No newline at end of file
diff --git
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
index 09665a210855..9847ffd6fb9e 100644
---
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
+++
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
@@ -3553,6 +3553,19 @@ public interface ComponentsBuilderFactory {
static Olingo4ComponentBuilderFactory.Olingo4ComponentBuilder olingo4() {
return Olingo4ComponentBuilderFactory.olingo4();
}
+ /**
+ * Once (camel-once)
+ * Camel Once component
+ *
+ * Category: core,scheduling
+ * Since: 4.170
+ * Maven coordinates: org.apache.camel:camel-once
+ *
+ * @return the dsl builder
+ */
+ static OnceComponentBuilderFactory.OnceComponentBuilder once() {
+ return OnceComponentBuilderFactory.once();
+ }
/**
* OpenSearch (camel-opensearch)
* Send requests to OpenSearch via Java Client API.
diff --git
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/OnceComponentBuilderFactory.java
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/OnceComponentBuilderFactory.java
new file mode 100644
index 000000000000..7de0e63c89b5
--- /dev/null
+++
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/OnceComponentBuilderFactory.java
@@ -0,0 +1,160 @@
+/* Generated by camel build tools - do NOT edit this file! */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.builder.component.dsl;
+
+import javax.annotation.processing.Generated;
+import org.apache.camel.Component;
+import org.apache.camel.builder.component.AbstractComponentBuilder;
+import org.apache.camel.builder.component.ComponentBuilder;
+import org.apache.camel.component.once.OnceComponent;
+
+/**
+ * Camel Once component
+ *
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.ComponentDslMojo")
+public interface OnceComponentBuilderFactory {
+
+ /**
+ * Once (camel-once)
+ * Camel Once component
+ *
+ * Category: core,scheduling
+ * Since: 4.170
+ * Maven coordinates: org.apache.camel:camel-once
+ *
+ * @return the dsl builder
+ */
+ static OnceComponentBuilder once() {
+ return new OnceComponentBuilderImpl();
+ }
+
+ /**
+ * Builder for the Once component.
+ */
+ interface OnceComponentBuilder extends ComponentBuilder<OnceComponent> {
+
+
+ /**
+ * 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 messages, or the likes, will
+ * now be processed as a message and handled by the routing Error
+ * Handler. Important: This is only possible if the 3rd party component
+ * allows Camel to be alerted if an exception was thrown. Some
+ * components handle this internally only, and therefore
+ * bridgeErrorHandler is not possible. In other situations we may
+ * improve the Camel component to hook into the 3rd party component and
+ * make this possible for future releases. By default the consumer will
+ * use the org.apache.camel.spi.ExceptionHandler to deal with
+ * exceptions, that will be logged at WARN or ERROR level and ignored.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: consumer
+ *
+ * @param bridgeErrorHandler the value to set
+ * @return the dsl builder
+ */
+ default OnceComponentBuilder bridgeErrorHandler(boolean
bridgeErrorHandler) {
+ doSetProperty("bridgeErrorHandler", bridgeErrorHandler);
+ return this;
+ }
+
+
+ /**
+ * Whether autowiring is enabled. This is used for automatic autowiring
+ * options (the option must be marked as autowired) by looking up in
the
+ * registry to find if there is a single instance of matching type,
+ * which then gets configured on the component. This can be used for
+ * automatic configuring JDBC data sources, JMS connection factories,
+ * AWS Clients, etc.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: true
+ * Group: advanced
+ *
+ * @param autowiredEnabled the value to set
+ * @return the dsl builder
+ */
+ default OnceComponentBuilder autowiredEnabled(boolean
autowiredEnabled) {
+ doSetProperty("autowiredEnabled", autowiredEnabled);
+ 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 OnceComponentBuilder delay(long delay) {
+ doSetProperty("delay", delay);
+ return this;
+ }
+
+
+ /**
+ * Whether Camel languages are supported such as simple,groovy.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: true
+ * Group: advanced
+ *
+ * @param languages the value to set
+ * @return the dsl builder
+ */
+ default OnceComponentBuilder languages(boolean languages) {
+ doSetProperty("languages", languages);
+ return this;
+ }
+ }
+
+ class OnceComponentBuilderImpl
+ extends AbstractComponentBuilder<OnceComponent>
+ implements OnceComponentBuilder {
+ @Override
+ protected OnceComponent buildConcreteComponent() {
+ return new OnceComponent();
+ }
+ @Override
+ protected boolean setPropertyOnComponent(
+ Component component,
+ String name,
+ Object value) {
+ switch (name) {
+ case "bridgeErrorHandler": ((OnceComponent)
component).setBridgeErrorHandler((boolean) value); return true;
+ case "autowiredEnabled": ((OnceComponent)
component).setAutowiredEnabled((boolean) value); return true;
+ case "delay": ((OnceComponent) component).setDelay((long) value);
return true;
+ case "languages": ((OnceComponent)
component).setLanguages((boolean) value); return true;
+ default: return false;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
index 33ad891feced..4b8424a248b3 100644
---
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
@@ -273,6 +273,7 @@ public interface EndpointBuilderFactory
org.apache.camel.builder.endpoint.dsl.OBSEndpointBuilderFactory.OBSBuilders,
org.apache.camel.builder.endpoint.dsl.Olingo2EndpointBuilderFactory.Olingo2Builders,
org.apache.camel.builder.endpoint.dsl.Olingo4EndpointBuilderFactory.Olingo4Builders,
+
org.apache.camel.builder.endpoint.dsl.OnceEndpointBuilderFactory.OnceBuilders,
org.apache.camel.builder.endpoint.dsl.OpenTelemetryEndpointBuilderFactory.OpenTelemetryBuilders,
org.apache.camel.builder.endpoint.dsl.OpensearchEndpointBuilderFactory.OpensearchBuilders,
org.apache.camel.builder.endpoint.dsl.OpenshiftBuildConfigsEndpointBuilderFactory.OpenshiftBuildConfigsBuilders,
diff --git
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java
index b85c75691bbf..eb38d68fd0ef 100644
---
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java
@@ -270,6 +270,7 @@ public interface EndpointBuilders
org.apache.camel.builder.endpoint.dsl.OBSEndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.Olingo2EndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.Olingo4EndpointBuilderFactory,
+ org.apache.camel.builder.endpoint.dsl.OnceEndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.OpenTelemetryEndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.OpensearchEndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.OpenshiftBuildConfigsEndpointBuilderFactory,
diff --git
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
index b800e5ffc61e..ed34bb0027e0 100644
---
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
@@ -11840,6 +11840,46 @@ public class StaticEndpointBuilders {
public static Olingo4EndpointBuilderFactory.Olingo4EndpointBuilder
olingo4(String componentName, String path) {
return Olingo4EndpointBuilderFactory.endpointBuilder(componentName,
path);
}
+ /**
+ * Once (camel-once)
+ * Camel Once component
+ *
+ * Category: core,scheduling
+ * Since: 4.170
+ * Maven coordinates: org.apache.camel:camel-once
+ *
+ * Syntax: <code>once:name</code>
+ *
+ * Path parameter: name (required)
+ * The logical name
+ *
+ * @param path name
+ * @return the dsl builder
+ */
+ public static OnceEndpointBuilderFactory.OnceEndpointBuilder once(String
path) {
+ return once("once", path);
+ }
+ /**
+ * Once (camel-once)
+ * Camel Once component
+ *
+ * Category: core,scheduling
+ * Since: 4.170
+ * Maven coordinates: org.apache.camel:camel-once
+ *
+ * Syntax: <code>once:name</code>
+ *
+ * Path parameter: name (required)
+ * The logical name
+ *
+ * @param componentName to use a custom component name for the endpoint
+ * instead of the default name
+ * @param path name
+ * @return the dsl builder
+ */
+ public static OnceEndpointBuilderFactory.OnceEndpointBuilder once(String
componentName, String path) {
+ return OnceEndpointBuilderFactory.endpointBuilder(componentName, path);
+ }
/**
* OpenSearch (camel-opensearch)
* Send requests to OpenSearch via Java Client API.
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
new file mode 100644
index 000000000000..57fd8ed44113
--- /dev/null
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OnceEndpointBuilderFactory.java
@@ -0,0 +1,427 @@
+/* Generated by camel build tools - do NOT edit this file! */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.builder.endpoint.dsl;
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.function.*;
+import java.util.stream.*;
+import javax.annotation.processing.Generated;
+import org.apache.camel.builder.EndpointConsumerBuilder;
+import org.apache.camel.builder.EndpointProducerBuilder;
+import org.apache.camel.builder.endpoint.AbstractEndpointBuilder;
+
+/**
+ * Camel Once component
+ *
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.EndpointDslMojo")
+public interface OnceEndpointBuilderFactory {
+
+ /**
+ * Builder for endpoint for the Once component.
+ */
+ public interface OnceEndpointBuilder
+ extends
+ EndpointConsumerBuilder {
+ default AdvancedOnceEndpointBuilder advanced() {
+ return (AdvancedOnceEndpointBuilder) this;
+ }
+
+ /**
+ * 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.
+ *
+ * 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.lang.String</code> type.
+ *
+ * Group: consumer
+ *
+ * @param body the value to set
+ * @return the dsl builder
+ */
+ default OnceEndpointBuilder body(String body) {
+ doSetProperty("body", body);
+ return this;
+ }
+ /**
+ * 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.
+ *
+ * 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.String></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).
+ *
+ * Group: consumer
+ *
+ * @param key the option key
+ * @param value the option value
+ * @return the dsl builder
+ */
+ default OnceEndpointBuilder headers(String key, Object value) {
+ doSetMultiValueProperty("headers", "header." + key, value);
+ return this;
+ }
+ /**
+ * 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.
+ *
+ * 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.String></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).
+ *
+ * Group: consumer
+ *
+ * @param values the values
+ * @return the dsl builder
+ */
+ default OnceEndpointBuilder headers(Map values) {
+ doSetMultiValueProperties("headers", "header.", values);
+ return this;
+ }
+ }
+
+ /**
+ * Advanced builder for endpoint for the Once component.
+ */
+ public interface AdvancedOnceEndpointBuilder
+ extends
+ EndpointConsumerBuilder {
+ default OnceEndpointBuilder basic() {
+ return (OnceEndpointBuilder) this;
+ }
+
+ /**
+ * 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 messages, or the likes, will
+ * now be processed as a message and handled by the routing Error
+ * Handler. Important: This is only possible if the 3rd party component
+ * allows Camel to be alerted if an exception was thrown. Some
+ * components handle this internally only, and therefore
+ * bridgeErrorHandler is not possible. In other situations we may
+ * improve the Camel component to hook into the 3rd party component and
+ * make this possible for future releases. By default the consumer will
+ * use the org.apache.camel.spi.ExceptionHandler to deal with
+ * exceptions, that will be logged at WARN or ERROR level and ignored.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: consumer (advanced)
+ *
+ * @param bridgeErrorHandler the value to set
+ * @return the dsl builder
+ */
+ default AdvancedOnceEndpointBuilder bridgeErrorHandler(boolean
bridgeErrorHandler) {
+ doSetProperty("bridgeErrorHandler", bridgeErrorHandler);
+ return this;
+ }
+ /**
+ * 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 messages, or the likes, will
+ * now be processed as a message and handled by the routing Error
+ * Handler. Important: This is only possible if the 3rd party component
+ * allows Camel to be alerted if an exception was thrown. Some
+ * components handle this internally only, and therefore
+ * bridgeErrorHandler is not possible. In other situations we may
+ * improve the Camel component to hook into the 3rd party component and
+ * make this possible for future releases. By default the consumer will
+ * use the org.apache.camel.spi.ExceptionHandler to deal with
+ * exceptions, that will be logged at WARN or ERROR level and ignored.
+ *
+ * The option will be converted to a <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: consumer (advanced)
+ *
+ * @param bridgeErrorHandler the value to set
+ * @return the dsl builder
+ */
+ default AdvancedOnceEndpointBuilder bridgeErrorHandler(String
bridgeErrorHandler) {
+ doSetProperty("bridgeErrorHandler", bridgeErrorHandler);
+ return this;
+ }
+ /**
+ * To let the consumer use a custom ExceptionHandler. Notice if the
+ * option bridgeErrorHandler is enabled then this option is not in use.
+ * By default the consumer will deal with exceptions, that will be
+ * logged at WARN or ERROR level and ignored.
+ *
+ * The option is a: <code>org.apache.camel.spi.ExceptionHandler</code>
+ * type.
+ *
+ * Group: consumer (advanced)
+ *
+ * @param exceptionHandler the value to set
+ * @return the dsl builder
+ */
+ default AdvancedOnceEndpointBuilder
exceptionHandler(org.apache.camel.spi.ExceptionHandler exceptionHandler) {
+ doSetProperty("exceptionHandler", exceptionHandler);
+ return this;
+ }
+ /**
+ * To let the consumer use a custom ExceptionHandler. Notice if the
+ * option bridgeErrorHandler is enabled then this option is not in use.
+ * By default the consumer will deal with exceptions, that will be
+ * logged at WARN or ERROR level and ignored.
+ *
+ * The option will be converted to a
+ * <code>org.apache.camel.spi.ExceptionHandler</code> type.
+ *
+ * Group: consumer (advanced)
+ *
+ * @param exceptionHandler the value to set
+ * @return the dsl builder
+ */
+ default AdvancedOnceEndpointBuilder exceptionHandler(String
exceptionHandler) {
+ doSetProperty("exceptionHandler", exceptionHandler);
+ return this;
+ }
+ /**
+ * Sets the exchange pattern when the consumer creates an exchange.
+ *
+ * The option is a: <code>org.apache.camel.ExchangePattern</code> type.
+ *
+ * Group: consumer (advanced)
+ *
+ * @param exchangePattern the value to set
+ * @return the dsl builder
+ */
+ default AdvancedOnceEndpointBuilder
exchangePattern(org.apache.camel.ExchangePattern exchangePattern) {
+ doSetProperty("exchangePattern", exchangePattern);
+ return this;
+ }
+ /**
+ * Sets the exchange pattern when the consumer creates an exchange.
+ *
+ * The option will be converted to a
+ * <code>org.apache.camel.ExchangePattern</code> type.
+ *
+ * Group: consumer (advanced)
+ *
+ * @param exchangePattern the value to set
+ * @return the dsl builder
+ */
+ default AdvancedOnceEndpointBuilder exchangePattern(String
exchangePattern) {
+ 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 properties 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: exchangeProperty.
+ *
+ * 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.String></code> type.
+ * The option is multivalued, and you can use the
+ * exchangeProperties(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 exchangeProperties(String key,
Object value) {
+ doSetMultiValueProperty("exchangeProperties", "exchangeProperty."
+ key, value);
+ return this;
+ }
+ /**
+ * The data to use as exchange properties 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: exchangeProperty.
+ *
+ * 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.String></code> type.
+ * The option is multivalued, and you can use the
+ * exchangeProperties(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 exchangeProperties(Map values) {
+ doSetMultiValueProperties("exchangeProperties",
"exchangeProperty.", values);
+ 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.String></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.String></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 {
+ /**
+ * Once (camel-once)
+ * Camel Once component
+ *
+ * Category: core,scheduling
+ * Since: 4.170
+ * Maven coordinates: org.apache.camel:camel-once
+ *
+ * Syntax: <code>once:name</code>
+ *
+ * Path parameter: name (required)
+ * The logical name
+ *
+ * @param path name
+ * @return the dsl builder
+ */
+ default OnceEndpointBuilder once(String path) {
+ return OnceEndpointBuilderFactory.endpointBuilder("once", path);
+ }
+ /**
+ * Once (camel-once)
+ * Camel Once component
+ *
+ * Category: core,scheduling
+ * Since: 4.170
+ * Maven coordinates: org.apache.camel:camel-once
+ *
+ * Syntax: <code>once:name</code>
+ *
+ * Path parameter: name (required)
+ * The logical name
+ *
+ * @param componentName to use a custom component name for the endpoint
+ * instead of the default name
+ * @param path name
+ * @return the dsl builder
+ */
+ default OnceEndpointBuilder once(String componentName, String path) {
+ return OnceEndpointBuilderFactory.endpointBuilder(componentName,
path);
+ }
+
+ }
+ static OnceEndpointBuilder endpointBuilder(String componentName, String
path) {
+ class OnceEndpointBuilderImpl extends AbstractEndpointBuilder
implements OnceEndpointBuilder, AdvancedOnceEndpointBuilder {
+ public OnceEndpointBuilderImpl(String path) {
+ super(componentName, path);
+ }
+ }
+ return new OnceEndpointBuilderImpl(path);
+ }
+}
\ No newline at end of file
diff --git
a/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties
b/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties
index ce1eedaf7eda..c5a8617d06e2 100644
---
a/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties
+++
b/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties
@@ -273,6 +273,7 @@
org.apache.camel.component.netty.http.NettyHttpComponent=camel:netty-http
org.apache.camel.component.nitrite.NitriteComponent=camel:nitrite
org.apache.camel.component.olingo2.Olingo2Component=camel:olingo2
org.apache.camel.component.olingo4.Olingo4Component=camel:olingo4
+org.apache.camel.component.once.OnceComponent=camel:once
org.apache.camel.component.opensearch.OpensearchComponent=camel:opensearch
org.apache.camel.component.openshift.build_configs.OpenshiftBuildConfigsComponent=camel:kubernetes
org.apache.camel.component.openshift.builds.OpenshiftBuildsComponent=camel:kubernetes
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/docs/yaml-dsl.adoc
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/docs/yaml-dsl.adoc
index 39613b850240..997a1a104096 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/docs/yaml-dsl.adoc
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/docs/yaml-dsl.adoc
@@ -139,18 +139,18 @@ To define an endpoint with the YAML dsl you have two
options:
*Available as of Camel 4.15*
It is now possible to inline Maps in the `parameters` section. However Camel
components rarely have options
-that are Map based, but when they do this makes it easier to use. For example
the plc4j component allow to
+that are Map based, but when they do this makes it easier to use. For example
the plc4x component allow to
configure _tags_ as a Map:
[source,yaml]
----
- from:
- uri: "timer://tick"
+ uri: "timer:tick"
parameters:
- period: "1s"
+ period: "1000"
steps:
- to:
- uri: "plc4j"
+ uri: "plc4x"
parameters:
driver: "some driver url here"
tags:
@@ -161,6 +161,8 @@ configure _tags_ as a Map:
In this example the _tags_ options is of Map type and can be configured using
YAML map syntax.
Because the keys use underscore, then they are quoted.
+IMPORTANT: To use map values for parameters, then the `uri` must only refer to
the name of the component, ie `plc4x` and not `plc4x:foo`
+
== Defining beans
In addition to the general support for creating beans provided by
xref:others:main.adoc#_specifying_custom_beans[Camel Main], the YAML DSL
provides a convenient syntax to define and configure them:
diff --git a/parent/pom.xml b/parent/pom.xml
index eb072867125d..e3560d744dee 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -2185,6 +2185,11 @@
<artifactId>camel-olingo4-api</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-once</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-openai</artifactId>