You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by nf...@apache.org on 2020/01/13 11:30:45 UTC

[camel] 01/08: CAMEL-14385: add a camel-cron component

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

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

commit 40690e59a8b490b0ac14371162fb9e703a1226a7
Author: Nicola Ferraro <ni...@gmail.com>
AuthorDate: Fri Jan 10 12:33:56 2020 +0100

    CAMEL-14385: add a camel-cron component
---
 components/{camel-quartz => camel-cron}/pom.xml    |  75 ++-----
 .../camel-cron/src/main/docs/cron-component.adoc   | 135 ++++++++++++
 .../apache/camel/component/cron/CronComponent.java | 109 ++++++++++
 .../apache/camel/component/cron/CronEndpoint.java  | 105 +++++++++
 .../apache/camel/component/cron/CronHelper.java    |  65 ++++++
 .../component/cron/api/CamelCronConfiguration.java |  66 ++++++
 .../camel/component/cron/api/CamelCronService.java |  29 +++
 .../camel/component/cron/CronLoaderTest.java       |  46 ++++
 .../camel/component/cron/CronPatternsTest.java     |  79 +++++++
 .../component/cron/DummyCamelCronService.java      |  51 +++++
 ...pache.camel.component.cron.api.CamelCronService |  18 ++
 .../src/test/resources/log4j2.properties           |  33 +++
 components/camel-quartz/pom.xml                    |   5 +
 .../src/main/docs/quartz-component.adoc            |  25 +++
 .../quartz/cron/CamelQuartzCronService.java        |  72 +++++++
 ...pache.camel.component.cron.api.CamelCronService |  18 ++
 .../quartz/cron/QuartzCronMappingTest.java         |  87 ++++++++
 .../component/quartz/cron/QuartzCronRouteTest.java |  45 ++++
 components/pom.xml                                 |   1 +
 .../builder/endpoint/EndpointBuilderFactory.java   |   1 +
 .../endpoint/dsl/CronEndpointBuilderFactory.java   | 235 +++++++++++++++++++++
 parent/pom.xml                                     |   5 +
 .../karaf/features/src/main/resources/features.xml |   4 +
 .../apache/camel/itest/karaf/CamelCronTest.java    |  33 +++
 24 files changed, 1288 insertions(+), 54 deletions(-)

diff --git a/components/camel-quartz/pom.xml b/components/camel-cron/pom.xml
similarity index 58%
copy from components/camel-quartz/pom.xml
copy to components/camel-cron/pom.xml
index 6575113..7881656 100644
--- a/components/camel-quartz/pom.xml
+++ b/components/camel-cron/pom.xml
@@ -26,37 +26,31 @@
         <version>3.1.0-SNAPSHOT</version>
     </parent>
 
-    <artifactId>camel-quartz</artifactId>
+    <artifactId>camel-cron</artifactId>
     <packaging>jar</packaging>
-    <name>Camel :: Quartz</name>
-    <description>Camel Quartz support</description>
+    <name>Camel :: Cron</name>
+    <description>Camel Cron Component</description>
+
+    <properties>
+    </properties>
 
     <dependencies>
+
+        <!-- requires camel-core -->
         <dependency>
             <groupId>org.apache.camel</groupId>
-            <artifactId>camel-support</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.quartz-scheduler</groupId>
-            <artifactId>quartz</artifactId>
-            <version>${quartz-version}</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>c3p0</groupId>
-                    <artifactId>c3p0</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>com.mchange</groupId>
-            <artifactId>c3p0</artifactId>
-            <version>${c3p0-version}</version>
+            <artifactId>camel-core-engine</artifactId>
         </dependency>
 
         <!-- test dependencies -->
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-timer</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -75,43 +69,16 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.apache.camel</groupId>
-            <artifactId>camel-test-spring</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-dbcp2</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <!-- for persistent test -->
-        <dependency>
-            <groupId>org.apache.derby</groupId>
-            <artifactId>derby</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-jdbc</artifactId>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-context-support</artifactId>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <version>${assertj-version}</version>
             <scope>test</scope>
         </dependency>
     </dependencies>
 
-    <build>
-        <plugins>
-            <plugin>
-                <artifactId>maven-surefire-plugin</artifactId>
-                <configuration>
-                    <forkCount>1</forkCount>
-                    <reuseForks>false</reuseForks>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
 </project>
diff --git a/components/camel-cron/src/main/docs/cron-component.adoc b/components/camel-cron/src/main/docs/cron-component.adoc
new file mode 100644
index 0000000..aa991e2
--- /dev/null
+++ b/components/camel-cron/src/main/docs/cron-component.adoc
@@ -0,0 +1,135 @@
+[[cron-component]]
+= Cron Component
+
+*Since Camel 3.1*
+
+// HEADER START
+*Only consumer is supported*
+// HEADER END
+
+The Cron component is a generic interface component that allows triggering events at specific time interval
+specified using the Unix cron syntax (e.g. `0/2 * * * * ?` to trigger an event every two seconds).
+
+Being an interface component, the Cron component does not contain a default implementation, instead it requires that the users plug
+the implementation of their choice.
+
+The following standard Camel components support the Cron endpoints:
+
+- Quartz
+
+The Cron component is also supported in **Camel K**, which can use the Kubernetes scheduler to trigger the routes when required by the cron expression.
+Camel K does not require additional libraries to be plugged when using cron expressions compatible with Kubernetes cron syntax.
+
+Maven users will need to add the following dependency to their `pom.xml`
+for this component:
+
+[source,xml]
+------------------------------------------------------------
+<dependency>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>camel-cron</artifactId>
+    <version>x.x.x</version>
+    <!-- use the same version as your Camel core version -->
+</dependency>
+------------------------------------------------------------
+
+Additional libraries may be needed in order to plug a specific implementation.
+
+== Options
+
+
+// component options: START
+The Cron component supports 4 options, which are listed below.
+
+
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *cronService* (advanced) | The id of the CamelCronService to use when multiple implementations are provided |  | String
+| *basicPropertyBinding* (advanced) | Whether the component should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities | false | boolean
+| *lazyStartProducer* (producer) | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and [...]
+| *bridgeErrorHandler* (consumer) | Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. 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. | false | boolean
+|===
+// component options: END
+
+
+
+
+
+// endpoint options: START
+The Cron endpoint is configured using URI syntax:
+
+----
+cron:name
+----
+
+with the following path and query parameters:
+
+=== Path Parameters (1 parameters):
+
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *name* | *Required* The name of the cron trigger |  | String
+|===
+
+
+=== Query Parameters (6 parameters):
+
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *bridgeErrorHandler* (consumer) | Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. 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. | false | boolean
+| *schedule* (consumer) | *Required* A cron expression that will be used to generate events |  | String
+| *exceptionHandler* (consumer) | 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. |  | ExceptionHandler
+| *exchangePattern* (consumer) | Sets the exchange pattern when the consumer creates an exchange. |  | ExchangePattern
+| *basicPropertyBinding* (advanced) | Whether the endpoint should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities | false | boolean
+| *synchronous* (advanced) | Sets whether synchronous processing should be strictly used, or Camel is allowed to use asynchronous processing (if supported). | false | boolean
+|===
+// endpoint options: END
+
+== Usage
+
+The component can be used to trigger events at specified times, as in the following example:
+
+[source,java]
+---------------------------------------------------------
+from("cron:tab?schedule=0/1+*+*+*+*+?")
+.setBody().constant("event")
+.log("${body}");
+---------------------------------------------------------
+
+The schedule expression `0/3+10+*+*+*+?` can be also written as `0/3 10 * * * ?` and triggers an event every three seconds only in the tenth minute of each hour.
+
+Parts in the schedule expression means (in order):
+
+- Seconds (optional)
+- Minutes
+- Hours
+- Day of month
+- Month
+- Day of week
+- Year (optional)
+
+Schedule expressions can be made of 5 to 7 parts. When expressions are composed of 6 parts, the first items is the "seconds" part (and year is considered missing).
+
+Other valid examples of schedule expressions are:
+
+- `0/2 * * * ?` (5 parts, an event every two minutes)
+- `0 0/2 * * * MON-FRI 2030` (7 parts, an event every two minutes only in year 2030)
+
+Routes can also be written using the XML DSL.
+
+[source,xml]
+-------------
+<route>
+    <from uri="cron:tab?schedule=0/1+*+*+*+*+?"/>
+    <setBody>
+      <constant>event</constant>
+    </setBody>
+    <to uri="log:info"/>
+</route>
+-------------
diff --git a/components/camel-cron/src/main/java/org/apache/camel/component/cron/CronComponent.java b/components/camel-cron/src/main/java/org/apache/camel/component/cron/CronComponent.java
new file mode 100644
index 0000000..acc6e8f
--- /dev/null
+++ b/components/camel-cron/src/main/java/org/apache/camel/component/cron/CronComponent.java
@@ -0,0 +1,109 @@
+/*
+ * 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.cron;
+
+import java.util.Map;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.cron.api.CamelCronConfiguration;
+import org.apache.camel.component.cron.api.CamelCronService;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.annotations.Component;
+import org.apache.camel.support.DefaultComponent;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * The Camel cron component.
+ */
+@Component("cron")
+public class CronComponent extends DefaultComponent {
+
+    @Metadata(label = "advanced")
+    private String cronService;
+
+    private CamelCronService service;
+
+    public CronComponent() {
+    }
+
+    @Override
+    public Endpoint createEndpoint(String uri, String remaining, Map<String, Object> properties) throws Exception {
+        initCamelCronService();
+
+        CamelCronConfiguration configuration = new CamelCronConfiguration();
+        configuration.setName(remaining);
+        setProperties(configuration, properties);
+        validate(configuration);
+
+        Endpoint delegate = this.service.createEndpoint(configuration);
+        CronEndpoint cronEndpoint = new CronEndpoint(uri, this, delegate, configuration);
+
+        if (properties.size() > 0) {
+            // Additional endpoint properties present
+            setProperties(cronEndpoint, properties);
+        }
+
+        return cronEndpoint;
+    }
+
+    /**
+     * Lazy creation of the CamelCronService
+     */
+    public synchronized void initCamelCronService() {
+        if (this.service == null) {
+            this.service = CronHelper.resolveCamelCronService(
+                    getCamelContext(),
+                    this.cronService
+            );
+
+            if (this.service == null) {
+                throw new RuntimeCamelException("Cannot find any CamelCronService: please add a valid implementation, such as 'camel-quartz', in order to use the 'camel-cron' component");
+            }
+
+            try {
+                getCamelContext().addService(this.service, true, false);
+            } catch (Exception e) {
+                throw new RuntimeCamelException(e);
+            }
+        }
+    }
+
+    public String getCronService() {
+        return cronService;
+    }
+
+    /**
+     * The id of the CamelCronService to use when multiple implementations
+     * are provided
+     */
+    public void setCronService(String cronService) {
+        this.cronService = cronService;
+    }
+
+    private void validate(CamelCronConfiguration configuration) {
+        ObjectHelper.notNull(configuration, "configuration");
+        ObjectHelper.notNull(configuration.getName(), "name");
+        ObjectHelper.notNull(configuration.getSchedule(), "schedule");
+
+        String[] parts = configuration.getSchedule().split("\\s");
+        if (parts.length < 5 || parts.length > 7) {
+            throw new IllegalArgumentException("Invalid number of parts in cron expression. Expected 5 to 7, got: " + parts.length);
+        }
+    }
+
+}
diff --git a/components/camel-cron/src/main/java/org/apache/camel/component/cron/CronEndpoint.java b/components/camel-cron/src/main/java/org/apache/camel/component/cron/CronEndpoint.java
new file mode 100644
index 0000000..d1ed013
--- /dev/null
+++ b/components/camel-cron/src/main/java/org/apache/camel/component/cron/CronEndpoint.java
@@ -0,0 +1,105 @@
+/*
+ * 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.cron;
+
+import org.apache.camel.Component;
+import org.apache.camel.Consumer;
+import org.apache.camel.DelegateEndpoint;
+import org.apache.camel.Endpoint;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.component.cron.api.CamelCronConfiguration;
+import org.apache.camel.spi.ExceptionHandler;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.support.DefaultEndpoint;
+
+@UriEndpoint(firstVersion = "3.1.0", scheme = "cron", title = "Cron", syntax = "cron:name", consumerOnly = true, label = "scheduling")
+public class CronEndpoint extends DefaultEndpoint implements DelegateEndpoint {
+
+    private Endpoint delegate;
+
+    @UriParam
+    private CamelCronConfiguration configuration;
+
+    public CronEndpoint(String endpointUri, Component component, Endpoint delegate, CamelCronConfiguration configuration) {
+        super(endpointUri, component);
+        this.delegate = delegate;
+        this.configuration = configuration;
+    }
+
+    @Override
+    public Endpoint getEndpoint() {
+        return delegate;
+    }
+
+    @Override
+    public Producer createProducer() throws Exception {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Consumer createConsumer(Processor processor) throws Exception {
+        return delegate.createConsumer(processor);
+    }
+
+    public CamelCronConfiguration getConfiguration() {
+        return configuration;
+    }
+
+    @Override
+    public void setSynchronous(boolean synchronous) {
+        super.setSynchronous(synchronous);
+        if (delegate instanceof DefaultEndpoint) {
+            ((DefaultEndpoint) delegate).setSynchronous(synchronous);
+        }
+    }
+
+    @Override
+    public void setBasicPropertyBinding(boolean basicPropertyBinding) {
+        super.setBasicPropertyBinding(basicPropertyBinding);
+        if (delegate instanceof DefaultEndpoint) {
+            ((DefaultEndpoint) delegate).setBasicPropertyBinding(basicPropertyBinding);
+        }
+    }
+
+    @Override
+    public void setExchangePattern(ExchangePattern exchangePattern) {
+        super.setExchangePattern(exchangePattern);
+        if (delegate instanceof DefaultEndpoint) {
+            ((DefaultEndpoint) delegate).setExchangePattern(exchangePattern);
+        }
+    }
+
+    @Override
+    public void setExceptionHandler(ExceptionHandler exceptionHandler) {
+        super.setExceptionHandler(exceptionHandler);
+        if (delegate instanceof DefaultEndpoint) {
+            ((DefaultEndpoint) delegate).setExceptionHandler(exceptionHandler);
+        }
+    }
+
+    @Override
+    public void setBridgeErrorHandler(boolean bridgeErrorHandler) {
+        super.setBridgeErrorHandler(bridgeErrorHandler);
+        if (delegate instanceof DefaultEndpoint) {
+            ((DefaultEndpoint) delegate).setBridgeErrorHandler(bridgeErrorHandler);
+        }
+    }
+
+}
diff --git a/components/camel-cron/src/main/java/org/apache/camel/component/cron/CronHelper.java b/components/camel-cron/src/main/java/org/apache/camel/component/cron/CronHelper.java
new file mode 100644
index 0000000..208c0e1
--- /dev/null
+++ b/components/camel-cron/src/main/java/org/apache/camel/component/cron/CronHelper.java
@@ -0,0 +1,65 @@
+/*
+ * 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.cron;
+
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.TreeMap;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.cron.api.CamelCronService;
+import org.apache.camel.support.CamelContextHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class CronHelper {
+    private static final Logger LOGGER = LoggerFactory.getLogger(CronHelper.class);
+
+    private CronHelper() {
+    }
+
+    /**
+     * Helper to lookup/create an instance of {@link CamelCronService}
+     */
+    public static CamelCronService resolveCamelCronService(CamelContext context, String name) {
+        // Lookup the registry first
+        CamelCronService service = ObjectHelper.isEmpty(name)
+                ? CamelContextHelper.findByType(context, CamelCronService.class)
+                : CamelContextHelper.lookup(context, name, CamelCronService.class);
+
+        if (service != null) {
+            // If the service is bound to the registry we assume it is already
+            // configured so let's return it as it is.
+            return service;
+        }
+
+        // Fallback to service loader
+        Map<String, CamelCronService> services = new TreeMap<>();
+        ServiceLoader.load(CamelCronService.class).forEach(s -> services.put(s.getId(), s));
+        if (name != null) {
+            return services.get(name);
+        }
+        if (services.size() == 1) {
+            return services.values().iterator().next();
+        } else if (services.size() > 1) {
+            LOGGER.warn("Multiple implementations found for CamelCronService: {}", services.keySet());
+        }
+        return null;
+    }
+
+}
diff --git a/components/camel-cron/src/main/java/org/apache/camel/component/cron/api/CamelCronConfiguration.java b/components/camel-cron/src/main/java/org/apache/camel/component/cron/api/CamelCronConfiguration.java
new file mode 100644
index 0000000..2f2f027
--- /dev/null
+++ b/components/camel-cron/src/main/java/org/apache/camel/component/cron/api/CamelCronConfiguration.java
@@ -0,0 +1,66 @@
+/*
+ * 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.cron.api;
+
+import java.util.StringJoiner;
+
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriParams;
+import org.apache.camel.spi.UriPath;
+
+@UriParams
+public class CamelCronConfiguration {
+
+    @UriPath
+    @Metadata(required = true)
+    private String name;
+
+    @UriParam
+    @Metadata(required = true)
+    private String schedule;
+
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * The name of the cron trigger
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getSchedule() {
+        return schedule;
+    }
+
+    /**
+     * A cron expression that will be used to generate events
+     */
+    public void setSchedule(String schedule) {
+        this.schedule = schedule;
+    }
+
+    @Override
+    public String toString() {
+        return new StringJoiner(", ", CamelCronConfiguration.class.getSimpleName() + "[", "]")
+                .add("name='" + name + "'")
+                .add("schedule='" + schedule + "'")
+                .toString();
+    }
+}
diff --git a/components/camel-cron/src/main/java/org/apache/camel/component/cron/api/CamelCronService.java b/components/camel-cron/src/main/java/org/apache/camel/component/cron/api/CamelCronService.java
new file mode 100644
index 0000000..c8f8daf
--- /dev/null
+++ b/components/camel-cron/src/main/java/org/apache/camel/component/cron/api/CamelCronService.java
@@ -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.
+ */
+package org.apache.camel.component.cron.api;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.spi.HasId;
+
+/**
+ * The contract that a cron implementation must respect.
+ */
+public interface CamelCronService extends HasId {
+
+    Endpoint createEndpoint(CamelCronConfiguration configuration) throws Exception;
+
+}
diff --git a/components/camel-cron/src/test/java/org/apache/camel/component/cron/CronLoaderTest.java b/components/camel-cron/src/test/java/org/apache/camel/component/cron/CronLoaderTest.java
new file mode 100644
index 0000000..79bb1d5
--- /dev/null
+++ b/components/camel-cron/src/test/java/org/apache/camel/component/cron/CronLoaderTest.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.cron;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+public class CronLoaderTest extends CamelTestSupport {
+
+    @Test
+    public void testDummyCronServiceLoading() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedBodiesReceived("x");
+        mock.assertIsSatisfied();
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("cron:tab?schedule=0/1 * * * * ?")
+                        .setBody().constant("x")
+                        .to("mock:result");
+
+            }
+        };
+    }
+}
diff --git a/components/camel-cron/src/test/java/org/apache/camel/component/cron/CronPatternsTest.java b/components/camel-cron/src/test/java/org/apache/camel/component/cron/CronPatternsTest.java
new file mode 100644
index 0000000..4553d8d
--- /dev/null
+++ b/components/camel-cron/src/test/java/org/apache/camel/component/cron/CronPatternsTest.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.cron;
+
+import org.apache.camel.FailedToCreateRouteException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+public class CronPatternsTest extends CamelTestSupport {
+
+    @Test(expected = FailedToCreateRouteException.class)
+    public void testTooManyParts() throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("cron:tab?schedule=0/1 * * * * ? 1 2")
+                        .to("mock:result");
+            }
+        });
+        context.start();
+    }
+
+    @Test(expected = FailedToCreateRouteException.class)
+    public void testTooLittleParts() throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("cron:tab?schedule=wrong pattern")
+                        .to("mock:result");
+            }
+        });
+        context.start();
+    }
+
+    @Test
+    public void testPlusInURI() throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("cron://name?schedule=0+0/5+12-18+?+*+MON-FRI")
+                        .to("mock:result");
+            }
+        });
+        context.start();
+    }
+
+    @Test(expected = FailedToCreateRouteException.class)
+    public void testPlusInURINok() throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("cron://name?schedule=0+0/5+12-18+?+*+MON-FRI+2019+1")
+                        .to("mock:result");
+            }
+        });
+        context.start();
+    }
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+}
diff --git a/components/camel-cron/src/test/java/org/apache/camel/component/cron/DummyCamelCronService.java b/components/camel-cron/src/test/java/org/apache/camel/component/cron/DummyCamelCronService.java
new file mode 100644
index 0000000..cfe49d0
--- /dev/null
+++ b/components/camel-cron/src/test/java/org/apache/camel/component/cron/DummyCamelCronService.java
@@ -0,0 +1,51 @@
+/*
+ * 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.cron;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.Endpoint;
+import org.apache.camel.component.cron.api.CamelCronConfiguration;
+import org.apache.camel.component.cron.api.CamelCronService;
+import org.apache.camel.component.timer.TimerComponent;
+
+public class DummyCamelCronService implements CamelCronService, CamelContextAware {
+
+    private CamelContext camelContext;
+
+    @Override
+    public Endpoint createEndpoint(CamelCronConfiguration configuration) throws Exception {
+        TimerComponent timerComponent = camelContext.getComponent("timer", TimerComponent.class);
+        return timerComponent.createEndpoint("timer:tick?period=1&delay=0");
+    }
+
+    @Override
+    public String getId() {
+        return "dummy";
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return this.camelContext;
+    }
+
+}
diff --git a/components/camel-cron/src/test/resources/META-INF/services/org.apache.camel.component.cron.api.CamelCronService b/components/camel-cron/src/test/resources/META-INF/services/org.apache.camel.component.cron.api.CamelCronService
new file mode 100644
index 0000000..bb79081
--- /dev/null
+++ b/components/camel-cron/src/test/resources/META-INF/services/org.apache.camel.component.cron.api.CamelCronService
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+org.apache.camel.component.cron.DummyCamelCronService
diff --git a/components/camel-cron/src/test/resources/log4j2.properties b/components/camel-cron/src/test/resources/log4j2.properties
new file mode 100644
index 0000000..536f7f6
--- /dev/null
+++ b/components/camel-cron/src/test/resources/log4j2.properties
@@ -0,0 +1,33 @@
+## ---------------------------------------------------------------------------
+## 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-reactive-streams-test.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+appender.stdout.type = Console
+appender.stdout.name = stdout
+appender.stdout.layout.type = PatternLayout
+appender.stdout.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+rootLogger.level = INFO
+rootLogger.appenderRef.file.ref = file
+
+#rootLogger.appenderRef.stdout.ref = stdout
+#logger.debug.name = org.apache.camel.component.reactive.streams
+#logger.debug.level = DEBUG
+#logger.debug.additivity = true
diff --git a/components/camel-quartz/pom.xml b/components/camel-quartz/pom.xml
index 6575113..1ccbd2a 100644
--- a/components/camel-quartz/pom.xml
+++ b/components/camel-quartz/pom.xml
@@ -37,6 +37,11 @@
             <artifactId>camel-support</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-cron</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
             <groupId>org.quartz-scheduler</groupId>
             <artifactId>quartz</artifactId>
             <version>${quartz-version}</version>
diff --git a/components/camel-quartz/src/main/docs/quartz-component.adoc b/components/camel-quartz/src/main/docs/quartz-component.adoc
index aedcc3b..b4dab5a 100644
--- a/components/camel-quartz/src/main/docs/quartz-component.adoc
+++ b/components/camel-quartz/src/main/docs/quartz-component.adoc
@@ -467,3 +467,28 @@ use the following as well:
     from("file:inbox?scheduler=spring&scheduler.cron=0/2+*+*+*+*+?")
        .to("bean:process");
 ----
+
+== Cron Component Support
+
+The Quartz component can be used as implementation of the Camel Cron component.
+
+
+Maven users will need to add the following additional dependency to their `pom.xml`:
+
+[source,xml]
+------------------------------------------------------------
+<dependency>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>camel-cron</artifactId>
+    <version>x.x.x</version>
+    <!-- use the same version as your Camel core version -->
+</dependency>
+------------------------------------------------------------
+
+Users can then use the cron component instead of the quartz component, as in the following route:
+
+[source,java]
+----
+    from("cron://name?schedule=0+0/5+12-18+?+*+MON-FRI")
+    .to("activemq:Totally.Rocks");
+----
diff --git a/components/camel-quartz/src/main/java/org/apache/camel/component/quartz/cron/CamelQuartzCronService.java b/components/camel-quartz/src/main/java/org/apache/camel/component/quartz/cron/CamelQuartzCronService.java
new file mode 100644
index 0000000..f78cf0e
--- /dev/null
+++ b/components/camel-quartz/src/main/java/org/apache/camel/component/quartz/cron/CamelQuartzCronService.java
@@ -0,0 +1,72 @@
+/*
+ * 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.quartz.cron;
+
+import java.util.Collections;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.Endpoint;
+import org.apache.camel.component.cron.api.CamelCronConfiguration;
+import org.apache.camel.component.cron.api.CamelCronService;
+import org.apache.camel.component.quartz.QuartzComponent;
+import org.apache.camel.util.URISupport;
+
+/**
+ * Allows the camel-quartz component to be used as implementation for camel-cron endpoints.
+ */
+public class CamelQuartzCronService implements CamelCronService, CamelContextAware {
+
+    private CamelContext context;
+
+    @Override
+    public Endpoint createEndpoint(CamelCronConfiguration configuration) throws Exception {
+        String schedule = convertSchedule(configuration.getSchedule());
+
+        String uriPath = "quartz://" + configuration.getName();
+        String query = URISupport.createQueryString(Collections.singletonMap("cron", schedule));
+        String uri = uriPath + "?" + query;
+
+        QuartzComponent quartz = context.getComponent("quartz", QuartzComponent.class);
+        return quartz.createEndpoint(uri);
+    }
+
+    private String convertSchedule(String schedule) {
+        String[] parts = schedule.split("\\s");
+        if (parts.length == 5) {
+            // Seconds are mandatory in Quartz, let's add them back
+            return "0 " + schedule;
+        }
+        return schedule;
+    }
+
+    @Override
+    public String getId() {
+        return "quartz";
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.context = camelContext;
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return this.context;
+    }
+
+}
diff --git a/components/camel-quartz/src/main/resources/META-INF/services/org.apache.camel.component.cron.api.CamelCronService b/components/camel-quartz/src/main/resources/META-INF/services/org.apache.camel.component.cron.api.CamelCronService
new file mode 100644
index 0000000..eb744e9
--- /dev/null
+++ b/components/camel-quartz/src/main/resources/META-INF/services/org.apache.camel.component.cron.api.CamelCronService
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+org.apache.camel.component.quartz.cron.CamelQuartzCronService
diff --git a/components/camel-quartz/src/test/java/org/apache/camel/component/quartz/cron/QuartzCronMappingTest.java b/components/camel-quartz/src/test/java/org/apache/camel/component/quartz/cron/QuartzCronMappingTest.java
new file mode 100644
index 0000000..d4d586f
--- /dev/null
+++ b/components/camel-quartz/src/test/java/org/apache/camel/component/quartz/cron/QuartzCronMappingTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.quartz.cron;
+
+import org.apache.camel.DelegateEndpoint;
+import org.apache.camel.Endpoint;
+import org.apache.camel.Route;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.component.quartz.BaseQuartzTest;
+import org.apache.camel.component.quartz.QuartzEndpoint;
+import org.junit.Test;
+
+public class QuartzCronMappingTest extends BaseQuartzTest {
+    protected MockEndpoint resultEndpoint;
+
+    @Test
+    public void test5PartsCronPattern() throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("cron://myName?schedule=* * * * ?")
+                        .id("cron")
+                        .to("mock:result");
+            }
+        });
+        context.start();
+        assertEquals("0 * * * * ?", getQuartzEndpoint(context.getRoute("cron")).getCron());
+    }
+
+    @Test
+    public void test6PartsCronPattern() throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("cron://myName?schedule=0/2 * * * * ?")
+                        .id("cron")
+                        .to("mock:result");
+            }
+        });
+        context.start();
+        assertEquals("0/2 * * * * ?", getQuartzEndpoint(context.getRoute("cron")).getCron());
+    }
+
+    @Test
+    public void testAdditionalProperties() throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("cron://myName?schedule=0/2+*+*+*+*+?&synchronous=true")
+                        .id("cron")
+                        .to("mock:result");
+            }
+        });
+        context.start();
+        assertEquals("0/2 * * * * ?", getQuartzEndpoint(context.getRoute("cron")).getCron());
+        assertTrue(getQuartzEndpoint(context.getRoute("cron")).isSynchronous());
+    }
+
+    private QuartzEndpoint getQuartzEndpoint(Route route) {
+        Endpoint endpoint = route.getEndpoint();
+        while (endpoint instanceof DelegateEndpoint) {
+            endpoint = ((DelegateEndpoint) endpoint).getEndpoint();
+        }
+        return (QuartzEndpoint) endpoint;
+    }
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+}
diff --git a/components/camel-quartz/src/test/java/org/apache/camel/component/quartz/cron/QuartzCronRouteTest.java b/components/camel-quartz/src/test/java/org/apache/camel/component/quartz/cron/QuartzCronRouteTest.java
new file mode 100644
index 0000000..00e11d5
--- /dev/null
+++ b/components/camel-quartz/src/test/java/org/apache/camel/component/quartz/cron/QuartzCronRouteTest.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.quartz.cron;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.component.quartz.BaseQuartzTest;
+import org.junit.Test;
+
+public class QuartzCronRouteTest extends BaseQuartzTest {
+    protected MockEndpoint resultEndpoint;
+
+    @Test
+    public void testCronQuartzRoute() throws Exception {
+        resultEndpoint = getMockEndpoint("mock:result");
+        resultEndpoint.expectedMinimumMessageCount(1);
+
+        // lets test the receive worked
+        resultEndpoint.assertIsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                from("cron://myName?schedule=0/1 * * * * ?")
+                        .to("mock:result");
+            }
+        };
+    }
+}
diff --git a/components/pom.xml b/components/pom.xml
index b4bb8d7..5b5d149 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -38,6 +38,7 @@
         <module>camel-bean</module>
         <module>camel-browse</module>
         <module>camel-controlbus</module>
+        <module>camel-cron</module>
         <module>camel-dataformat</module>
         <module>camel-dataset</module>
         <module>camel-direct</module>
diff --git a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
index 321d4b8..f07ae56c 100644
--- a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
+++ b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
@@ -71,6 +71,7 @@ public interface EndpointBuilderFactory extends
         CordaEndpointBuilderFactory,
         CouchDbEndpointBuilderFactory,
         CouchbaseEndpointBuilderFactory,
+        CronEndpointBuilderFactory,
         CryptoCmsEndpointBuilderFactory,
         CwEndpointBuilderFactory,
         CxfEndpointBuilderFactory,
diff --git a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/CronEndpointBuilderFactory.java b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/CronEndpointBuilderFactory.java
new file mode 100644
index 0000000..729f40b
--- /dev/null
+++ b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/CronEndpointBuilderFactory.java
@@ -0,0 +1,235 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.builder.endpoint.dsl;
+
+import javax.annotation.Generated;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.builder.EndpointConsumerBuilder;
+import org.apache.camel.builder.EndpointProducerBuilder;
+import org.apache.camel.builder.endpoint.AbstractEndpointBuilder;
+import org.apache.camel.spi.ExceptionHandler;
+
+/**
+ * Camel Cron Component
+ * 
+ * Generated by camel-package-maven-plugin - do not edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.EndpointDslMojo")
+public interface CronEndpointBuilderFactory {
+
+
+    /**
+     * Builder for endpoint for the Cron component.
+     */
+    public interface CronEndpointBuilder extends EndpointConsumerBuilder {
+        default AdvancedCronEndpointBuilder advanced() {
+            return (AdvancedCronEndpointBuilder) this;
+        }
+        /**
+         * Allows for bridging the consumer to the Camel routing Error Handler,
+         * which mean any exceptions occurred while the consumer is trying to
+         * pickup incoming messages, or the likes, will now be processed as a
+         * message and handled by the routing Error Handler. 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
+         */
+        default CronEndpointBuilder bridgeErrorHandler(
+                boolean bridgeErrorHandler) {
+            doSetProperty("bridgeErrorHandler", bridgeErrorHandler);
+            return this;
+        }
+        /**
+         * Allows for bridging the consumer to the Camel routing Error Handler,
+         * which mean any exceptions occurred while the consumer is trying to
+         * pickup incoming messages, or the likes, will now be processed as a
+         * message and handled by the routing Error Handler. 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
+         */
+        default CronEndpointBuilder bridgeErrorHandler(String bridgeErrorHandler) {
+            doSetProperty("bridgeErrorHandler", bridgeErrorHandler);
+            return this;
+        }
+        /**
+         * A cron expression that will be used to generate events.
+         * 
+         * The option is a: <code>java.lang.String</code> type.
+         * 
+         * Required: true
+         * Group: consumer
+         */
+        default CronEndpointBuilder schedule(String schedule) {
+            doSetProperty("schedule", schedule);
+            return this;
+        }
+    }
+
+    /**
+     * Advanced builder for endpoint for the Cron component.
+     */
+    public interface AdvancedCronEndpointBuilder
+            extends
+                EndpointConsumerBuilder {
+        default CronEndpointBuilder basic() {
+            return (CronEndpointBuilder) 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)
+         */
+        default AdvancedCronEndpointBuilder exceptionHandler(
+                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)
+         */
+        default AdvancedCronEndpointBuilder 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)
+         */
+        default AdvancedCronEndpointBuilder exchangePattern(
+                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)
+         */
+        default AdvancedCronEndpointBuilder exchangePattern(
+                String exchangePattern) {
+            doSetProperty("exchangePattern", exchangePattern);
+            return this;
+        }
+        /**
+         * Whether the endpoint should use basic property binding (Camel 2.x) or
+         * the newer property binding with additional capabilities.
+         * 
+         * The option is a: <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: advanced
+         */
+        default AdvancedCronEndpointBuilder basicPropertyBinding(
+                boolean basicPropertyBinding) {
+            doSetProperty("basicPropertyBinding", basicPropertyBinding);
+            return this;
+        }
+        /**
+         * Whether the endpoint should use basic property binding (Camel 2.x) or
+         * the newer property binding with additional capabilities.
+         * 
+         * The option will be converted to a <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: advanced
+         */
+        default AdvancedCronEndpointBuilder basicPropertyBinding(
+                String basicPropertyBinding) {
+            doSetProperty("basicPropertyBinding", basicPropertyBinding);
+            return this;
+        }
+        /**
+         * Sets whether synchronous processing should be strictly used, or Camel
+         * is allowed to use asynchronous processing (if supported).
+         * 
+         * The option is a: <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: advanced
+         */
+        default AdvancedCronEndpointBuilder synchronous(boolean synchronous) {
+            doSetProperty("synchronous", synchronous);
+            return this;
+        }
+        /**
+         * Sets whether synchronous processing should be strictly used, or Camel
+         * is allowed to use asynchronous processing (if supported).
+         * 
+         * The option will be converted to a <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: advanced
+         */
+        default AdvancedCronEndpointBuilder synchronous(String synchronous) {
+            doSetProperty("synchronous", synchronous);
+            return this;
+        }
+    }
+    /**
+     * Cron (camel-cron)
+     * Camel Cron Component
+     * 
+     * Category: scheduling
+     * Since: 3.1
+     * Maven coordinates: org.apache.camel:camel-cron
+     * 
+     * Syntax: <code>cron:name</code>
+     * 
+     * Path parameter: name (required)
+     * The name of the cron trigger
+     */
+    default CronEndpointBuilder cron(String path) {
+        class CronEndpointBuilderImpl extends AbstractEndpointBuilder implements CronEndpointBuilder, AdvancedCronEndpointBuilder {
+            public CronEndpointBuilderImpl(String path) {
+                super("cron", path);
+            }
+        }
+        return new CronEndpointBuilderImpl(path);
+    }
+}
\ No newline at end of file
diff --git a/parent/pom.xml b/parent/pom.xml
index b3358ce..a0b2e87 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -1144,6 +1144,11 @@
       </dependency>
       <dependency>
         <groupId>org.apache.camel</groupId>
+        <artifactId>camel-cron</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.camel</groupId>
         <artifactId>camel-crypto</artifactId>
         <version>${project.version}</version>
       </dependency>
diff --git a/platforms/karaf/features/src/main/resources/features.xml b/platforms/karaf/features/src/main/resources/features.xml
index 26bd843..7134c2a 100644
--- a/platforms/karaf/features/src/main/resources/features.xml
+++ b/platforms/karaf/features/src/main/resources/features.xml
@@ -763,6 +763,10 @@
     <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.couchbase-client/${couchbase-client-bundle-version}</bundle>
     <bundle>mvn:org.apache.camel/camel-couchbase/${project.version}</bundle>
   </feature>
+  <feature name='camel-cron' version='${project.version}' start-level='50'>
+    <feature version='${project.version}'>camel-core</feature>
+    <bundle>mvn:org.apache.camel/camel-cron/${project.version}</bundle>
+  </feature>
   <feature name='camel-crypto' version='${project.version}' start-level='50'>
     <feature version='${project.version}'>camel-core</feature>
     <bundle dependency='true'>mvn:commons-codec/commons-codec/${commons-codec-version}</bundle>
diff --git a/tests/camel-itest-karaf/src/test/java/org/apache/camel/itest/karaf/CamelCronTest.java b/tests/camel-itest-karaf/src/test/java/org/apache/camel/itest/karaf/CamelCronTest.java
new file mode 100644
index 0000000..e07b8a7
--- /dev/null
+++ b/tests/camel-itest-karaf/src/test/java/org/apache/camel/itest/karaf/CamelCronTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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.itest.karaf;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.junit.PaxExam;
+
+@RunWith(PaxExam.class)
+public class CamelCronTest extends BaseKarafTest {
+
+    public static final String COMPONENT = extractName(CamelCronTest.class);
+
+    @Test
+    public void test() throws Exception {
+        testComponent(COMPONENT);
+    }
+
+}