You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pp...@apache.org on 2022/03/31 09:47:44 UTC

[camel-quarkus] 12/43: 3579 Improve quartz test coverage

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

ppalaga pushed a commit to branch 2.7.x
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git

commit de1c436b35ec29455fc607cbd6e068d8b78e86ef
Author: JiriOndrusek <on...@gmail.com>
AuthorDate: Tue Mar 8 09:44:20 2022 +0100

    3579 Improve quartz test coverage
---
 .../ROOT/pages/reference/extensions/quartz.adoc    |  58 ++++++
 extensions/quartz/deployment/pom.xml               |  10 +
 .../quartz/deployment/QuartzProcessor.java         |  58 +++++-
 extensions/quartz/runtime/pom.xml                  |  14 ++
 .../quartz/runtime/src/main/doc/limitations.adoc   |   4 +
 extensions/quartz/runtime/src/main/doc/usage.adoc  |  46 +++++
 .../CamelQuarkusQuartzConnectionProvider.java      |  66 +++++++
 integration-tests/quartz/pom.xml                   |  41 ++++
 .../component/quartz/it/QuartzResource.java        |  74 ++++++++
 .../quarkus/component/quartz/it/QuartzRoutes.java  |  29 ++-
 .../src/main/resources/application.properties      |  47 +++++
 .../db/migration/V1.0.1__QuarkusQuartz.sql         | 207 +++++++++++++++++++++
 .../src/main/resources/quartz-node-A.properties    |  62 ++++++
 .../src/main/resources/quartz-node-B.properties    |  63 +++++++
 .../src/main/resources/quartz-node-C.properties    |  67 +++++++
 .../quartz/src/main/resources/quartz.properties    |  26 +++
 .../quarkus/component/quartz/it/QuartzTest.java    |  81 ++++++++
 pom.xml                                            |   1 +
 poms/bom/pom.xml                                   |   5 +
 19 files changed, 957 insertions(+), 2 deletions(-)

diff --git a/docs/modules/ROOT/pages/reference/extensions/quartz.adoc b/docs/modules/ROOT/pages/reference/extensions/quartz.adoc
index 99c7cdf..196d77f 100644
--- a/docs/modules/ROOT/pages/reference/extensions/quartz.adoc
+++ b/docs/modules/ROOT/pages/reference/extensions/quartz.adoc
@@ -38,3 +38,61 @@ Or add the coordinates to your existing project:
 ----
 
 Check the xref:user-guide/index.adoc[User guide] for more information about writing Camel Quarkus applications.
+
+== Usage
+
+=== Clustering
+
+There are two options how to run Quartz in clustered mode:
+
+==== Quarkus based
+
+This is the preferred option. Follow the https://quarkus.io/guides/quartz[scheduling periodic tasks quartz guide].
+
+- Define database configuration in `application.properties`.
+- Use for example `flyway` to create database tables required for `Quartz`.
+
+===== Quartz based with an Agroal datasource
+
+Follow the http://www.quartz-scheduler.org/documentation/quartz-1.8.6/configuration/ConfigJDBCJobStoreClustering.html#configure-clustering-with-jdbc-jobstore[Configure Clustering with JDBC-JobStore Guide] with different DS configuration:
+
+- Use `quartz.properties` to configure `JobStore`.
+- Define datasource via quarkus (see the https://quarkus.io/guides/datasource[Quarkus datasource documentation)] and use `CamelQuarkusQuartzConnectionProvider` as `ConnectionProvider` in `quartz.properties`:
+
+```
+...
+org.quartz.jobStore.dataSource = myDS
+
+# datasource configuration
+org.quartz.dataSource.myDS.connectionProvider.class = org.apache.camel.quarkus.component.quartz.CamelQuarkusQuartzConnectionProvider
+org.quartz.dataSource.myDSB.dataSourceName = ds_name_if_not_set_default_ds_will_be_used
+```
+
+
+- You can use for example `flyway` to create database tables required for `Quartz`.
+
+===== Quartz based
+
+You can follow the http://www.quartz-scheduler.org/documentation/quartz-1.8.6/configuration/ConfigJDBCJobStoreClustering.html#configure-clustering-with-jdbc-jobstore[Configure Clustering with JDBC-JobStore Guide] without any modification:
+
+```
+...
+org.quartz.jobStore.dataSource = myDS
+
+# datasource configuration
+org.quartz.dataSource.myDS.driver = org.postgresql.Driver
+
+# datasource configuration
+org.quartz.dataSource.myDS.URL=jdbc:postgresql://localhost:5432/default
+org.quartz.dataSource.myDS.user = quarkus
+org.quartz.dataSource.myDS.password = quarkus
+```
+
+
+== Camel Quarkus limitations
+
+=== JDBC Job Store
+
+Quartz's property `org.quartz.jobStore.useProperties` is set to `true` and can not be modified. The value is forced by the Quarkus Quartz extension.
+See the Quartz documentation for more information about `org.quartz.jobStore.useProperties`.
+
diff --git a/extensions/quartz/deployment/pom.xml b/extensions/quartz/deployment/pom.xml
index a62f311..67c4dc4 100644
--- a/extensions/quartz/deployment/pom.xml
+++ b/extensions/quartz/deployment/pom.xml
@@ -33,6 +33,12 @@
         <dependency>
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-quartz-deployment</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>mchange-commons-java</artifactId>
+                    <groupId>com.mchange</groupId>
+                </exclusion>
+            </exclusions>
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
@@ -42,6 +48,10 @@
             <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-quartz</artifactId>
         </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-agroal-deployment</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/extensions/quartz/deployment/src/main/java/org/apache/camel/quarkus/component/quartz/deployment/QuartzProcessor.java b/extensions/quartz/deployment/src/main/java/org/apache/camel/quarkus/component/quartz/deployment/QuartzProcessor.java
index 0174322..86d9262 100644
--- a/extensions/quartz/deployment/src/main/java/org/apache/camel/quarkus/component/quartz/deployment/QuartzProcessor.java
+++ b/extensions/quartz/deployment/src/main/java/org/apache/camel/quarkus/component/quartz/deployment/QuartzProcessor.java
@@ -16,10 +16,19 @@
  */
 package org.apache.camel.quarkus.component.quartz.deployment;
 
+import io.quarkus.bootstrap.model.ApplicationModel;
+import io.quarkus.deployment.annotations.BuildProducer;
 import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
 import io.quarkus.deployment.builditem.FeatureBuildItem;
+import io.quarkus.deployment.builditem.IndexDependencyBuildItem;
 import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.NativeImageSystemPropertyBuildItem;
 import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
+import io.quarkus.deployment.pkg.builditem.CurateOutcomeBuildItem;
+import org.jboss.jandex.DotName;
+import org.jboss.jandex.IndexView;
+import org.quartz.impl.jdbcjobstore.StdJDBCDelegate;
 
 class QuartzProcessor {
 
@@ -27,8 +36,17 @@ class QuartzProcessor {
     private static final String[] QUARTZ_JOB_CLASSES = new String[] {
             "org.apache.camel.component.quartz.CamelJob",
             "org.apache.camel.component.quartz.StatefulCamelJob",
-            "org.apache.camel.pollconsumer.quartz.QuartzScheduledPollConsumerJob"
+            "org.apache.camel.pollconsumer.quartz.QuartzScheduledPollConsumerJob",
+            "org.quartz.utils.C3p0PoolingConnectionProvider"
     };
+    private static final String[] QUARTZ_JOB_CLASSES_WITH_METHODS = new String[] {
+            "org.quartz.impl.jdbcjobstore.JobStoreTX",
+            "org.quartz.impl.jdbcjobstore.JobStoreSupport",
+            "org.quartz.impl.triggers.SimpleTriggerImpl",
+            "org.quartz.impl.triggers.AbstractTrigger",
+            "org.apache.camel.quarkus.component.quartz.CamelQuarkusQuartzConnectionProvider"
+    };
+    private static final DotName SQL_JDBC_DELEGATE = DotName.createSimple(StdJDBCDelegate.class.getName());
 
     @BuildStep
     FeatureBuildItem feature() {
@@ -44,4 +62,42 @@ class QuartzProcessor {
     ReflectiveClassBuildItem registerForReflection() {
         return new ReflectiveClassBuildItem(false, false, QUARTZ_JOB_CLASSES);
     }
+
+    @BuildStep
+    ReflectiveClassBuildItem registerForReflectionWithMethods() {
+        return new ReflectiveClassBuildItem(true, false, QUARTZ_JOB_CLASSES_WITH_METHODS);
+    }
+
+    @BuildStep
+    void registerForReflection(BuildProducer<ReflectiveClassBuildItem> reflectiveClasses,
+            CombinedIndexBuildItem combinedIndex, CurateOutcomeBuildItem curateOutcome) {
+        IndexView index = combinedIndex.getIndex();
+
+        ApplicationModel applicationModel = curateOutcome.getApplicationModel();
+        boolean oracleBlobIsPresent = applicationModel.getDependencies().stream()
+                .anyMatch(d -> d.getGroupId().equals("com.oracle.database.jdbc"));
+
+        final String[] delegatesImpl = index
+                .getAllKnownSubclasses(SQL_JDBC_DELEGATE)
+                .stream()
+                .map(c -> c.name().toString())
+                .filter(n -> oracleBlobIsPresent || !n.contains("oracle"))
+                .toArray(String[]::new);
+
+        reflectiveClasses.produce(new ReflectiveClassBuildItem(false, true, delegatesImpl));
+
+    }
+
+    @BuildStep
+    void indexSaxonHe(BuildProducer<IndexDependencyBuildItem> deps) {
+        deps.produce(new IndexDependencyBuildItem("org.quartz-scheduler", "quartz"));
+    }
+
+    @BuildStep
+    NativeImageSystemPropertyBuildItem disableJMX() {
+
+        return new NativeImageSystemPropertyBuildItem("com.mchange.v2.c3p0.management.ManagementCoordinator",
+                "com.mchange.v2.c3p0.management.NullManagementCoordinator");
+    }
+
 }
diff --git a/extensions/quartz/runtime/pom.xml b/extensions/quartz/runtime/pom.xml
index 5ebf9f6..091c12f 100644
--- a/extensions/quartz/runtime/pom.xml
+++ b/extensions/quartz/runtime/pom.xml
@@ -50,6 +50,12 @@
         <dependency>
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-quartz</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>mchange-commons-java</artifactId>
+                    <groupId>com.mchange</groupId>
+                </exclusion>
+            </exclusions>
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
@@ -59,6 +65,14 @@
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-quartz</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.mchange</groupId>
+            <artifactId>c3p0</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-agroal</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/extensions/quartz/runtime/src/main/doc/limitations.adoc b/extensions/quartz/runtime/src/main/doc/limitations.adoc
new file mode 100644
index 0000000..dbff30b
--- /dev/null
+++ b/extensions/quartz/runtime/src/main/doc/limitations.adoc
@@ -0,0 +1,4 @@
+=== JDBC Job Store
+
+Quartz's property `org.quartz.jobStore.useProperties` is set to `true` and can not be modified. The value is forced by the Quarkus Quartz extension.
+See the Quartz documentation for more information about `org.quartz.jobStore.useProperties`.
\ No newline at end of file
diff --git a/extensions/quartz/runtime/src/main/doc/usage.adoc b/extensions/quartz/runtime/src/main/doc/usage.adoc
new file mode 100644
index 0000000..0d34bbf
--- /dev/null
+++ b/extensions/quartz/runtime/src/main/doc/usage.adoc
@@ -0,0 +1,46 @@
+=== Clustering
+
+There are two options how to run Quartz in clustered mode:
+
+==== Quarkus based
+
+This is the preferred option. Follow the https://quarkus.io/guides/quartz[scheduling periodic tasks quartz guide].
+
+- Define database configuration in `application.properties`.
+- Use for example `flyway` to create database tables required for `Quartz`.
+
+===== Quartz based with an Agroal datasource
+
+Follow the http://www.quartz-scheduler.org/documentation/quartz-1.8.6/configuration/ConfigJDBCJobStoreClustering.html#configure-clustering-with-jdbc-jobstore[Configure Clustering with JDBC-JobStore Guide] with different DS configuration:
+
+- Use `quartz.properties` to configure `JobStore`.
+- Define datasource via quarkus (see the https://quarkus.io/guides/datasource[Quarkus datasource documentation)] and use `CamelQuarkusQuartzConnectionProvider` as `ConnectionProvider` in `quartz.properties`:
+
+```
+...
+org.quartz.jobStore.dataSource = myDS
+
+# datasource configuration
+org.quartz.dataSource.myDS.connectionProvider.class = org.apache.camel.quarkus.component.quartz.CamelQuarkusQuartzConnectionProvider
+org.quartz.dataSource.myDSB.dataSourceName = ds_name_if_not_set_default_ds_will_be_used
+```
+
+
+- You can use for example `flyway` to create database tables required for `Quartz`.
+
+===== Quartz based
+
+You can follow the http://www.quartz-scheduler.org/documentation/quartz-1.8.6/configuration/ConfigJDBCJobStoreClustering.html#configure-clustering-with-jdbc-jobstore[Configure Clustering with JDBC-JobStore Guide] without any modification:
+
+```
+...
+org.quartz.jobStore.dataSource = myDS
+
+# datasource configuration
+org.quartz.dataSource.myDS.driver = org.postgresql.Driver
+
+# datasource configuration
+org.quartz.dataSource.myDS.URL=jdbc:postgresql://localhost:5432/default
+org.quartz.dataSource.myDS.user = quarkus
+org.quartz.dataSource.myDS.password = quarkus
+```
\ No newline at end of file
diff --git a/extensions/quartz/runtime/src/main/java/org/apache/camel/quarkus/component/quartz/CamelQuarkusQuartzConnectionProvider.java b/extensions/quartz/runtime/src/main/java/org/apache/camel/quarkus/component/quartz/CamelQuarkusQuartzConnectionProvider.java
new file mode 100644
index 0000000..cea123e
--- /dev/null
+++ b/extensions/quartz/runtime/src/main/java/org/apache/camel/quarkus/component/quartz/CamelQuarkusQuartzConnectionProvider.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.quarkus.component.quartz;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import io.agroal.api.AgroalDataSource;
+import io.quarkus.agroal.DataSource.DataSourceLiteral;
+import io.quarkus.arc.Arc;
+import io.quarkus.arc.ArcContainer;
+import io.quarkus.arc.InstanceHandle;
+import org.quartz.utils.ConnectionProvider;
+
+public class CamelQuarkusQuartzConnectionProvider implements ConnectionProvider {
+    private AgroalDataSource dataSource;
+    private String dataSourceName;
+
+    @Override
+    public Connection getConnection() throws SQLException {
+        return dataSource.getConnection();
+    }
+
+    @Override
+    public void shutdown() {
+        // Do nothing as the connection will be closed inside the Agroal extension
+    }
+
+    @Override
+    public void initialize() {
+        final ArcContainer container = Arc.container();
+        final InstanceHandle<AgroalDataSource> instanceHandle;
+        final boolean useDefaultDataSource = dataSourceName == null || "".equals(dataSourceName.trim());
+        if (useDefaultDataSource) {
+            instanceHandle = container.instance(AgroalDataSource.class);
+        } else {
+            instanceHandle = container.instance(AgroalDataSource.class, new DataSourceLiteral(dataSourceName));
+        }
+        if (instanceHandle.isAvailable()) {
+            this.dataSource = instanceHandle.get();
+        } else {
+            String message = String.format(
+                    "JDBC Store configured but '%s' datasource is missing. You can configure your datasource by following the guide available at: https://quarkus.io/guides/datasource",
+                    useDefaultDataSource ? "default" : dataSourceName);
+            throw new IllegalStateException(message);
+        }
+    }
+
+    public void setDataSourceName(String dataSourceName) {
+        this.dataSourceName = dataSourceName;
+    }
+}
diff --git a/integration-tests/quartz/pom.xml b/integration-tests/quartz/pom.xml
index 864a944..d3fb49f 100644
--- a/integration-tests/quartz/pom.xml
+++ b/integration-tests/quartz/pom.xml
@@ -47,6 +47,26 @@
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-resteasy</artifactId>
         </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy-jackson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-jdbc-postgresql</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-jdbc-h2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-agroal</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-flyway</artifactId>
+        </dependency>
 
         <!-- test dependencies -->
         <dependency>
@@ -59,6 +79,16 @@
             <artifactId>rest-assured</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.awaitility</groupId>
+            <artifactId>awaitility</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-integration-test-support</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
 
@@ -140,6 +170,17 @@
                 </dependency>
             </dependencies>
         </profile>
+        <profile>
+            <id>skip-testcontainers-tests</id>
+            <activation>
+                <property>
+                    <name>skip-testcontainers-tests</name>
+                </property>
+            </activation>
+            <properties>
+                <skipTests>true</skipTests>
+            </properties>
+        </profile>
     </profiles>
 
 </project>
diff --git a/integration-tests/quartz/src/main/java/org/apache/camel/quarkus/component/quartz/it/QuartzResource.java b/integration-tests/quartz/src/main/java/org/apache/camel/quarkus/component/quartz/it/QuartzResource.java
index 1abac2f..f0e6c19 100644
--- a/integration-tests/quartz/src/main/java/org/apache/camel/quarkus/component/quartz/it/QuartzResource.java
+++ b/integration-tests/quartz/src/main/java/org/apache/camel/quarkus/component/quartz/it/QuartzResource.java
@@ -16,21 +16,74 @@
  */
 package org.apache.camel.quarkus.component.quartz.it;
 
+import java.util.Map;
+import java.util.stream.Collectors;
+
 import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 
+import org.apache.camel.CamelContext;
 import org.apache.camel.ConsumerTemplate;
+import org.apache.camel.Exchange;
+import org.apache.camel.component.quartz.QuartzComponent;
+import org.apache.camel.util.CollectionHelper;
+import org.quartz.CronTrigger;
 
 @Path("/quartz")
 public class QuartzResource {
 
     @Inject
+    CamelContext camelContext;
+
+    @Inject
     ConsumerTemplate consumerTemplate;
 
+    @javax.enterprise.inject.Produces
+    @Singleton
+    @Named("quartzFromProperties")
+    public QuartzComponent createQuartzFromProperties() {
+        return new QuartzComponent();
+    }
+
+    @javax.enterprise.inject.Produces
+    @Singleton
+    @Named("quartzNodeA")
+    public QuartzComponent createQuartzNodeA() {
+        return new QuartzComponent();
+    }
+
+    @javax.enterprise.inject.Produces
+    @Singleton
+    @Named("quartzNodeB")
+    public QuartzComponent createQuartzNodeB() {
+        return new QuartzComponent();
+    }
+
+    @javax.enterprise.inject.Produces
+    @Singleton
+    @Named("quartzNodeC")
+    public QuartzComponent createQuartzNodeC() {
+        return new QuartzComponent();
+    }
+
+    @Path("/getNameAndResult")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public Map<String, String> getSchedulerNameAndResult(@QueryParam("componentName") String componentName,
+            @QueryParam("fromEndpoint") String fromEndpoint) throws Exception {
+
+        QuartzComponent comp = camelContext.getComponent(componentName, QuartzComponent.class);
+
+        return CollectionHelper.mapOf("name", comp.getScheduler().getSchedulerName().replaceFirst(camelContext.getName(), ""),
+                "result", consumerTemplate.receiveBody("seda:" + fromEndpoint + "-result", 5000, String.class));
+    }
+
     @Path("/get")
     @GET
     @Produces(MediaType.TEXT_PLAIN)
@@ -38,4 +91,25 @@ public class QuartzResource {
         return consumerTemplate.receiveBody("seda:" + fromEndpoint + "-result", 5000, String.class);
     }
 
+    @Path("/getHeaders")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public Map<String, String> getHeaders(@QueryParam("fromEndpoint") String fromEndpoint) throws Exception {
+        Exchange exchange = consumerTemplate.receive("seda:" + fromEndpoint + "-result", 5000);
+
+        return exchange.getMessage().getHeaders().entrySet().stream().filter(e -> e.getValue() instanceof String)
+                .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().toString()));
+    }
+
+    @Path("/getMisfire")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public Map<String, String> getMisfire(@QueryParam("fromEndpoint") String fromEndpoint) throws Exception {
+        Exchange exchange = consumerTemplate.receive("seda:" + fromEndpoint + "-result", 5000);
+
+        System.out.println(exchange.getMessage().getHeaders().keySet().stream().collect(Collectors.joining(",")));
+        return CollectionHelper.mapOf("timezone",
+                exchange.getMessage().getHeader("trigger", CronTrigger.class).getTimeZone().getID(),
+                "misfire", exchange.getMessage().getHeader("trigger", CronTrigger.class).getMisfireInstruction() + "");
+    }
 }
diff --git a/integration-tests/quartz/src/main/java/org/apache/camel/quarkus/component/quartz/it/QuartzRoutes.java b/integration-tests/quartz/src/main/java/org/apache/camel/quarkus/component/quartz/it/QuartzRoutes.java
index d836ee5..0b0b098 100644
--- a/integration-tests/quartz/src/main/java/org/apache/camel/quarkus/component/quartz/it/QuartzRoutes.java
+++ b/integration-tests/quartz/src/main/java/org/apache/camel/quarkus/component/quartz/it/QuartzRoutes.java
@@ -22,12 +22,39 @@ public class QuartzRoutes extends RouteBuilder {
 
     @Override
     public void configure() throws Exception {
-        from("quartz:0/1 * * * * ?")
+
+        from("quartz:quartz/1 * * * * ?")
                 .setBody(constant("Hello Camel Quarkus quartz"))
                 .to("seda:quartz-result");
 
         from("cron:tab?schedule=0/1 * * * * ?")
                 .setBody(constant("Hello Camel Quarkus cron"))
                 .to("seda:cron-result");
+
+        from("quartzFromProperties:properties/* 1 * * * ")
+                .setBody(constant("Hello Camel Quarkus Quartz Properties"))
+                .to("seda:quartz-properties-result");
+
+        // cron trigger
+        from("quartz://cronTrigger?cron=0/1+*+*+*+*+?&trigger.timeZone=Europe/Stockholm")
+                .setBody(constant("Hello Camel Quarkus Quartz From Cron Trigger"))
+                .to("seda:quartz-cron-trigger-result");
+
+        from("quartz://misfire?cron=0/1+*+*+*+*+?&trigger.timeZone=Europe/Stockholm&trigger.misfireInstruction=2")
+                .to("seda:quartz-cron-misfire-result");
+
+        // Features unavailable on Camel 3.14.2
+        // from("quartzNodeA:nodeA/1 * * * * ")
+        //         .setBody(constant("Hello Camel Quarkus Quartz NodeA"))
+        //         .to("seda:quartz-nodeA-result");
+        //
+        // from("quartzNodeB:nodeB/1 * * * * ")
+        //         .setBody(constant("Hello Camel Quarkus Quartz NodeB"))
+        //         .to("seda:quartz-nodeB-result");
+        //
+        // from("quartzNodeC:nodeC/1 * * * * ")
+        //         .setBody(constant("Hello Camel Quarkus Quartz NodeC"))
+        //         .to("seda:quartz-nodeC-result");
+
     }
 }
diff --git a/integration-tests/quartz/src/main/resources/application.properties b/integration-tests/quartz/src/main/resources/application.properties
new file mode 100644
index 0000000..0805de0
--- /dev/null
+++ b/integration-tests/quartz/src/main/resources/application.properties
@@ -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.
+## ---------------------------------------------------------------------------
+
+camel.component.quartzNodeA.propertiesFile=quartz-node-A.properties
+camel.component.quartzNodeB.propertiesFile=quartz-node-B.properties
+camel.component.quartzFromProperties.propertiesFile=quartz.properties
+
+quarkus.native.resources.includes = quartz*.properties
+
+quarkus.datasource.devservices.enabled = true
+
+#postgresql db
+quarkus.datasource.db-kind=postgresql
+# flyway to create Quartz tables
+quarkus.flyway.connect-retries=10
+quarkus.flyway.table=flyway_quarkus_history
+quarkus.flyway.migrate-at-start=true
+quarkus.flyway.baseline-on-migrate=true
+quarkus.flyway.baseline-version=1.0
+quarkus.flyway.baseline-description=Quartz
+
+# h2 db
+quarkus.datasource.h2ds.db-kind=h2
+# flyway to create Quartz tables
+quarkus.flyway.h2ds.connect-retries=10
+quarkus.flyway.h2ds.table=flyway_quarkus_history
+quarkus.flyway.h2ds.migrate-at-start=true
+quarkus.flyway.h2ds.baseline-on-migrate=true
+quarkus.flyway.h2ds.baseline-version=1.0
+quarkus.flyway.h2ds.baseline-description=Quartz
+
+#fixed port is required to use quarz.properties for DS configuration
+quarkus.datasource.devservices.port = 5432
\ No newline at end of file
diff --git a/integration-tests/quartz/src/main/resources/db/migration/V1.0.1__QuarkusQuartz.sql b/integration-tests/quartz/src/main/resources/db/migration/V1.0.1__QuarkusQuartz.sql
new file mode 100644
index 0000000..e62f739
--- /dev/null
+++ b/integration-tests/quartz/src/main/resources/db/migration/V1.0.1__QuarkusQuartz.sql
@@ -0,0 +1,207 @@
+--
+-- 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.
+--
+
+CREATE TABLE QRTZ_JOB_DETAILS
+(
+    SCHED_NAME        VARCHAR(120) NOT NULL,
+    JOB_NAME          VARCHAR(200) NOT NULL,
+    JOB_GROUP         VARCHAR(200) NOT NULL,
+    DESCRIPTION       VARCHAR(250) NULL,
+    JOB_CLASS_NAME    VARCHAR(250) NOT NULL,
+    IS_DURABLE        BOOL         NOT NULL,
+    IS_NONCONCURRENT  BOOL         NOT NULL,
+    IS_UPDATE_DATA    BOOL         NOT NULL,
+    REQUESTS_RECOVERY BOOL         NOT NULL,
+    JOB_DATA          BYTEA        NULL,
+    PRIMARY KEY (SCHED_NAME, JOB_NAME, JOB_GROUP)
+);
+
+CREATE TABLE QRTZ_TRIGGERS
+(
+    SCHED_NAME     VARCHAR(120) NOT NULL,
+    TRIGGER_NAME   VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP  VARCHAR(200) NOT NULL,
+    JOB_NAME       VARCHAR(200) NOT NULL,
+    JOB_GROUP      VARCHAR(200) NOT NULL,
+    DESCRIPTION    VARCHAR(250) NULL,
+    NEXT_FIRE_TIME BIGINT       NULL,
+    PREV_FIRE_TIME BIGINT       NULL,
+    PRIORITY       INTEGER      NULL,
+    TRIGGER_STATE  VARCHAR(16)  NOT NULL,
+    TRIGGER_TYPE   VARCHAR(8)   NOT NULL,
+    START_TIME     BIGINT       NOT NULL,
+    END_TIME       BIGINT       NULL,
+    CALENDAR_NAME  VARCHAR(200) NULL,
+    MISFIRE_INSTR  SMALLINT     NULL,
+    JOB_DATA       BYTEA        NULL,
+    PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME, JOB_NAME, JOB_GROUP)
+        REFERENCES QRTZ_JOB_DETAILS (SCHED_NAME, JOB_NAME, JOB_GROUP)
+);
+
+CREATE TABLE QRTZ_SIMPLE_TRIGGERS
+(
+    SCHED_NAME      VARCHAR(120) NOT NULL,
+    TRIGGER_NAME    VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP   VARCHAR(200) NOT NULL,
+    REPEAT_COUNT    BIGINT       NOT NULL,
+    REPEAT_INTERVAL BIGINT       NOT NULL,
+    TIMES_TRIGGERED BIGINT       NOT NULL,
+    PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
+        REFERENCES QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
+);
+
+CREATE TABLE QRTZ_CRON_TRIGGERS
+(
+    SCHED_NAME      VARCHAR(120) NOT NULL,
+    TRIGGER_NAME    VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP   VARCHAR(200) NOT NULL,
+    CRON_EXPRESSION VARCHAR(120) NOT NULL,
+    TIME_ZONE_ID    VARCHAR(80),
+    PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
+        REFERENCES QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
+);
+
+CREATE TABLE QRTZ_SIMPROP_TRIGGERS
+(
+    SCHED_NAME    VARCHAR(120)   NOT NULL,
+    TRIGGER_NAME  VARCHAR(200)   NOT NULL,
+    TRIGGER_GROUP VARCHAR(200)   NOT NULL,
+    STR_PROP_1    VARCHAR(512)   NULL,
+    STR_PROP_2    VARCHAR(512)   NULL,
+    STR_PROP_3    VARCHAR(512)   NULL,
+    INT_PROP_1    INT            NULL,
+    INT_PROP_2    INT            NULL,
+    LONG_PROP_1   BIGINT         NULL,
+    LONG_PROP_2   BIGINT         NULL,
+    DEC_PROP_1    NUMERIC(13, 4) NULL,
+    DEC_PROP_2    NUMERIC(13, 4) NULL,
+    BOOL_PROP_1   BOOL           NULL,
+    BOOL_PROP_2   BOOL           NULL,
+    PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
+        REFERENCES QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
+);
+
+CREATE TABLE QRTZ_BLOB_TRIGGERS
+(
+    SCHED_NAME    VARCHAR(120) NOT NULL,
+    TRIGGER_NAME  VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    BLOB_DATA     BYTEA        NULL,
+    PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
+        REFERENCES QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
+);
+
+CREATE TABLE QRTZ_CALENDARS
+(
+    SCHED_NAME    VARCHAR(120) NOT NULL,
+    CALENDAR_NAME VARCHAR(200) NOT NULL,
+    CALENDAR      BYTEA        NOT NULL,
+    PRIMARY KEY (SCHED_NAME, CALENDAR_NAME)
+);
+
+
+CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS
+(
+    SCHED_NAME    VARCHAR(120) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    PRIMARY KEY (SCHED_NAME, TRIGGER_GROUP)
+);
+
+CREATE TABLE QRTZ_FIRED_TRIGGERS
+(
+    SCHED_NAME        VARCHAR(120) NOT NULL,
+    ENTRY_ID          VARCHAR(95)  NOT NULL,
+    TRIGGER_NAME      VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP     VARCHAR(200) NOT NULL,
+    INSTANCE_NAME     VARCHAR(200) NOT NULL,
+    FIRED_TIME        BIGINT       NOT NULL,
+    SCHED_TIME        BIGINT       NOT NULL,
+    PRIORITY          INTEGER      NOT NULL,
+    STATE             VARCHAR(16)  NOT NULL,
+    JOB_NAME          VARCHAR(200) NULL,
+    JOB_GROUP         VARCHAR(200) NULL,
+    IS_NONCONCURRENT  BOOL         NULL,
+    REQUESTS_RECOVERY BOOL         NULL,
+    PRIMARY KEY (SCHED_NAME, ENTRY_ID)
+);
+
+CREATE TABLE QRTZ_SCHEDULER_STATE
+(
+    SCHED_NAME        VARCHAR(120) NOT NULL,
+    INSTANCE_NAME     VARCHAR(200) NOT NULL,
+    LAST_CHECKIN_TIME BIGINT       NOT NULL,
+    CHECKIN_INTERVAL  BIGINT       NOT NULL,
+    PRIMARY KEY (SCHED_NAME, INSTANCE_NAME)
+);
+
+CREATE TABLE QRTZ_LOCKS
+(
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    LOCK_NAME  VARCHAR(40)  NOT NULL,
+    PRIMARY KEY (SCHED_NAME, LOCK_NAME)
+);
+
+CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY
+    ON QRTZ_JOB_DETAILS (SCHED_NAME, REQUESTS_RECOVERY);
+CREATE INDEX IDX_QRTZ_J_GRP
+    ON QRTZ_JOB_DETAILS (SCHED_NAME, JOB_GROUP);
+
+CREATE INDEX IDX_QRTZ_T_J
+    ON QRTZ_TRIGGERS (SCHED_NAME, JOB_NAME, JOB_GROUP);
+CREATE INDEX IDX_QRTZ_T_JG
+    ON QRTZ_TRIGGERS (SCHED_NAME, JOB_GROUP);
+CREATE INDEX IDX_QRTZ_T_C
+    ON QRTZ_TRIGGERS (SCHED_NAME, CALENDAR_NAME);
+CREATE INDEX IDX_QRTZ_T_G
+    ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_GROUP);
+CREATE INDEX IDX_QRTZ_T_STATE
+    ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_N_STATE
+    ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP, TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_N_G_STATE
+    ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_GROUP, TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME
+    ON QRTZ_TRIGGERS (SCHED_NAME, NEXT_FIRE_TIME);
+CREATE INDEX IDX_QRTZ_T_NFT_ST
+    ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_STATE, NEXT_FIRE_TIME);
+CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE
+    ON QRTZ_TRIGGERS (SCHED_NAME, MISFIRE_INSTR, NEXT_FIRE_TIME);
+CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE
+    ON QRTZ_TRIGGERS (SCHED_NAME, MISFIRE_INSTR, NEXT_FIRE_TIME, TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP
+    ON QRTZ_TRIGGERS (SCHED_NAME, MISFIRE_INSTR, NEXT_FIRE_TIME, TRIGGER_GROUP, TRIGGER_STATE);
+
+CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME
+    ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, INSTANCE_NAME);
+CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY
+    ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, INSTANCE_NAME, REQUESTS_RECOVERY);
+CREATE INDEX IDX_QRTZ_FT_J_G
+    ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, JOB_NAME, JOB_GROUP);
+CREATE INDEX IDX_QRTZ_FT_JG
+    ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, JOB_GROUP);
+CREATE INDEX IDX_QRTZ_FT_T_G
+    ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP);
+CREATE INDEX IDX_QRTZ_FT_TG
+    ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, TRIGGER_GROUP);
+
+
+COMMIT;
\ No newline at end of file
diff --git a/integration-tests/quartz/src/main/resources/quartz-node-A.properties b/integration-tests/quartz/src/main/resources/quartz-node-A.properties
new file mode 100644
index 0000000..3c54402
--- /dev/null
+++ b/integration-tests/quartz/src/main/resources/quartz-node-A.properties
@@ -0,0 +1,62 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+#============================================================================
+# Configure Main Scheduler Properties
+#============================================================================
+
+org.quartz.jdbc.initialize-schema=always
+org.quartz.scheduler.instanceName = NodeA
+org.quartz.scheduler.instanceId = AUTO
+
+#============================================================================
+# Configure ThreadPool
+#============================================================================
+
+org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
+org.quartz.threadPool.threadCount = 25
+org.quartz.threadPool.threadPriority = 5
+
+#============================================================================
+# Configure JobStore
+#============================================================================
+
+org.quartz.jobStore.misfireThreshold = 60000
+
+org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
+org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
+org.quartz.jobStore.useProperties = true
+org.quartz.jobStore.dataSource = myDSA
+org.quartz.jobStore.tablePrefix = QRTZ_
+
+org.quartz.jobStore.isClustered = true
+org.quartz.jobStore.clusterCheckinInterval = 500
+
+
+#============================================================================
+# Configure Datasources
+#============================================================================
+
+# datasource configuration
+org.quartz.dataSource.myDSA.connectionProvider.class = org.apache.camel.quarkus.component.quartz.CamelQuarkusQuartzConnectionProvider
+
+#
+#============================================================================
+# Disable JMX
+#============================================================================
+
+#com.mchange.v2.c3p0.management.ManagementCoordinator = com.mchange.v2.c3p0.management.NullManagementCoordinator
\ No newline at end of file
diff --git a/integration-tests/quartz/src/main/resources/quartz-node-B.properties b/integration-tests/quartz/src/main/resources/quartz-node-B.properties
new file mode 100644
index 0000000..210acdd
--- /dev/null
+++ b/integration-tests/quartz/src/main/resources/quartz-node-B.properties
@@ -0,0 +1,63 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+#============================================================================
+# Configure Main Scheduler Properties
+#============================================================================
+
+org.quartz.jdbc.initialize-schema=always
+org.quartz.scheduler.instanceName = NodeB
+org.quartz.scheduler.instanceId = AUTO
+
+#============================================================================
+# Configure ThreadPool
+#============================================================================
+
+org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
+org.quartz.threadPool.threadCount = 25
+org.quartz.threadPool.threadPriority = 5
+
+#============================================================================
+# Configure JobStore
+#============================================================================
+
+org.quartz.jobStore.misfireThreshold = 60000
+
+org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
+org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
+org.quartz.jobStore.useProperties = true
+org.quartz.jobStore.dataSource = myDSB
+org.quartz.jobStore.tablePrefix = QRTZ_
+
+org.quartz.jobStore.isClustered = true
+org.quartz.jobStore.clusterCheckinInterval = 500
+
+
+#============================================================================
+# Configure Datasources
+#============================================================================
+
+# datasource configuration
+org.quartz.dataSource.myDSB.connectionProvider.class = org.apache.camel.quarkus.component.quartz.CamelQuarkusQuartzConnectionProvider
+org.quartz.dataSource.myDSB.dataSourceName = h2ds
+
+#
+#============================================================================
+# Disable JMX
+#============================================================================
+
+#com.mchange.v2.c3p0.management.ManagementCoordinator = com.mchange.v2.c3p0.management.NullManagementCoordinator
\ No newline at end of file
diff --git a/integration-tests/quartz/src/main/resources/quartz-node-C.properties b/integration-tests/quartz/src/main/resources/quartz-node-C.properties
new file mode 100644
index 0000000..11c2432
--- /dev/null
+++ b/integration-tests/quartz/src/main/resources/quartz-node-C.properties
@@ -0,0 +1,67 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+#============================================================================
+# Configure Main Scheduler Properties
+#============================================================================
+
+org.quartz.jdbc.initialize-schema=always
+org.quartz.scheduler.instanceName = NodeB
+org.quartz.scheduler.instanceId = AUTO
+
+#============================================================================
+# Configure ThreadPool
+#============================================================================
+
+org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
+org.quartz.threadPool.threadCount = 25
+org.quartz.threadPool.threadPriority = 5
+
+#============================================================================
+# Configure JobStore
+#============================================================================
+
+org.quartz.jobStore.misfireThreshold = 60000
+
+org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
+org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
+org.quartz.jobStore.useProperties = true
+org.quartz.jobStore.dataSource = myDSC
+org.quartz.jobStore.tablePrefix = QRTZ_
+
+org.quartz.jobStore.isClustered = true
+org.quartz.jobStore.clusterCheckinInterval = 500
+
+
+#============================================================================
+# Configure Datasources
+#============================================================================
+
+# datasource configuration
+org.quartz.dataSource.myDSC.driver = org.postgresql.Driver
+
+# datasource configuration
+org.quartz.dataSource.myDSC.URL=jdbc:postgresql://localhost:5432/default
+org.quartz.dataSource.myDSC.user = quarkus
+org.quartz.dataSource.myDSC.password = quarkus
+
+#
+#============================================================================
+# Disable JMX
+#============================================================================
+
+#com.mchange.v2.c3p0.management.ManagementCoordinator = com.mchange.v2.c3p0.management.NullManagementCoordinator
\ No newline at end of file
diff --git a/integration-tests/quartz/src/main/resources/quartz.properties b/integration-tests/quartz/src/main/resources/quartz.properties
new file mode 100644
index 0000000..caf7989
--- /dev/null
+++ b/integration-tests/quartz/src/main/resources/quartz.properties
@@ -0,0 +1,26 @@
+## ---------------------------------------------------------------------------
+## 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.quartz.scheduler.instanceName = MyScheduler
+org.quartz.scheduler.instanceId = 2
+org.quartz.scheduler.rmi.export = false
+org.quartz.scheduler.rmi.proxy = false
+
+org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
+org.quartz.threadPool.threadCount = 3
+
+org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
diff --git a/integration-tests/quartz/src/test/java/org/apache/camel/quarkus/component/quartz/it/QuartzTest.java b/integration-tests/quartz/src/test/java/org/apache/camel/quarkus/component/quartz/it/QuartzTest.java
index f37bb6f..2e4d08f 100644
--- a/integration-tests/quartz/src/test/java/org/apache/camel/quarkus/component/quartz/it/QuartzTest.java
+++ b/integration-tests/quartz/src/test/java/org/apache/camel/quarkus/component/quartz/it/QuartzTest.java
@@ -18,6 +18,8 @@ package org.apache.camel.quarkus.component.quartz.it;
 
 import io.quarkus.test.junit.QuarkusTest;
 import io.restassured.RestAssured;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
 
@@ -36,4 +38,83 @@ class QuartzTest {
                 .statusCode(200)
                 .body(is("Hello Camel Quarkus " + component));
     }
+
+    @Test
+    @Disabled("Features unavailable on Camel 3.14.2")
+    public void testProperties() {
+        RestAssured.given()
+                .queryParam("fromEndpoint", "quartz-properties")
+                .queryParam("componentName", "quartzFromProperties")
+                .get("/quartz/getNameAndResult")
+                .then()
+                .statusCode(200)
+                .body("name", is("MyScheduler-"),
+                        "result", is("Hello Camel Quarkus Quartz Properties"));
+    }
+
+    @Test
+    public void testCronTrigger() {
+        RestAssured.given()
+                .queryParam("fromEndpoint", "quartz-cron-trigger")
+                .get("/quartz/get")
+                .then()
+                .statusCode(200)
+                .body(is("Hello Camel Quarkus Quartz From Cron Trigger"));
+
+    }
+
+    @Test
+    public void testHeaders() {
+        RestAssured.given()
+                .queryParam("fromEndpoint", "quartz")
+                .get("/quartz/getHeaders")
+                .then()
+                .statusCode(200)
+                .body("triggerName", is("1 * * * * "));
+    }
+
+    @Test
+    public void testMisfire() {
+        RestAssured.given()
+                .queryParam("fromEndpoint", "quartz-cron-misfire")
+                .get("/quartz/getMisfire")
+                .then()
+                .statusCode(200)
+                .body("timezone", is("Europe/Stockholm"),
+                        "misfire", is("2"));
+    }
+
+    @Test
+    @Disabled("Features unavailable on Camel 3.14.2")
+    public void testClustered() throws InterruptedException {
+        RestAssured.given()
+                .queryParam("fromEndpoint", "quartz-nodeA")
+                .get("/quartz/get")
+                .then()
+                .statusCode(200)
+                .body(is("Hello Camel Quarkus Quartz NodeA"));
+    }
+
+    @Test
+    @Disabled("Features unavailable on Camel 3.14.2")
+    public void testClusteredWithNamedDS() throws InterruptedException {
+        RestAssured.given()
+                .queryParam("fromEndpoint", "quartz-nodeB")
+                .get("/quartz/get")
+                .then()
+                .statusCode(200)
+                .body(is("Hello Camel Quarkus Quartz NodeB"));
+    }
+
+    @Test
+    @Disabled("Features unavailable on Camel 3.14.2")
+    public void testClusteredWithoutDS() throws InterruptedException {
+        //NodeB uses h2 db, which is not initialized therefore no message will be received
+        RestAssured.given()
+                .queryParam("fromEndpoint", "quartz-nodeC")
+                .get("/quartz/get")
+                .then()
+                .statusCode(200)
+                .body(is("Hello Camel Quarkus Quartz NodeC"));
+    }
 }
diff --git a/pom.xml b/pom.xml
index f1308bc..43646c6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,6 +69,7 @@
         <aws-java-sdk.version>1.11.714</aws-java-sdk.version>
         <azure-sdk-bom.version>1.0.5</azure-sdk-bom.version><!-- Keep in sync with camel-azure component versions -->
         <bouncycastle.version>1.70</bouncycastle.version><!-- @sync io.quarkus:quarkus-bom:${quarkus.version} dep:org.bouncycastle:bcprov-jdk15on -->
+        <c3p0.version>${c3p0-version}</c3p0.version>
         <commons-beanutils.version>${commons-beanutils-version}</commons-beanutils.version>
         <commons-cli.version>1.4</commons-cli.version><!-- keep in sync with Quarkus, via quarkus-bootstrap-core -->
         <commons-collections.version>3.2.2</commons-collections.version><!-- used by hbase, should be pretty stable as commons-collections are not developed actively anymore -->
diff --git a/poms/bom/pom.xml b/poms/bom/pom.xml
index 0f0ba6f..6421d27 100644
--- a/poms/bom/pom.xml
+++ b/poms/bom/pom.xml
@@ -6271,6 +6271,11 @@
                 <version>${zxing.version}</version>
             </dependency>
             <dependency>
+                <groupId>com.mchange</groupId>
+                <artifactId>c3p0</artifactId>
+                <version>${c3p0.version}</version>
+            </dependency>
+            <dependency>
                 <groupId>com.orbitz.consul</groupId>
                 <artifactId>consul-client</artifactId>
                 <version>${consul-client.version}</version>