You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by gh...@apache.org on 2020/07/01 12:18:27 UTC

[felix-dev] branch feature/FELIX-6265-support-cron-expressions-without-quartz created (now 8f78a18)

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

ghenzler pushed a change to branch feature/FELIX-6265-support-cron-expressions-without-quartz
in repository https://gitbox.apache.org/repos/asf/felix-dev.git.


      at 8f78a18  FELIX-6265 Prepare for support of simple cron expressions without quartz

This branch includes the following new commits:

     new 8f78a18  FELIX-6265 Prepare for support of simple cron expressions without quartz

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[felix-dev] 01/01: FELIX-6265 Prepare for support of simple cron expressions without quartz

Posted by gh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ghenzler pushed a commit to branch feature/FELIX-6265-support-cron-expressions-without-quartz
in repository https://gitbox.apache.org/repos/asf/felix-dev.git

commit 8f78a180b24740a2c8711c6369b90f5b64fde968
Author: georg.henzler <ge...@netcentric.biz>
AuthorDate: Wed Jul 1 14:04:47 2020 +0200

    FELIX-6265 Prepare for support of simple cron expressions without quartz
---
 .../executor/async/AsyncHealthCheckExecutor.java   |  9 ++--
 .../hc/core/impl/monitor/HealthCheckMonitor.java   | 10 ++--
 .../core/impl/scheduling/AsyncQuartzCronJob.java   | 15 +++---
 .../core/impl/scheduling/AsyncSimpleCronJob.java   | 38 +++++++++++++++
 ...nSchedulerProvider.java => CronJobFactory.java} | 56 ++++++++++++++--------
 ...eduler.java => QuartzCronSchedulerBuilder.java} | 17 ++-----
 6 files changed, 93 insertions(+), 52 deletions(-)

diff --git a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckExecutor.java b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckExecutor.java
index fc598d1..13134eb 100644
--- a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckExecutor.java
+++ b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckExecutor.java
@@ -39,8 +39,7 @@ import org.apache.felix.hc.core.impl.executor.HealthCheckFuture.Callback;
 import org.apache.felix.hc.core.impl.executor.HealthCheckResultCache;
 import org.apache.felix.hc.core.impl.scheduling.AsyncIntervalJob;
 import org.apache.felix.hc.core.impl.scheduling.AsyncJob;
-import org.apache.felix.hc.core.impl.scheduling.AsyncQuartzCronJob;
-import org.apache.felix.hc.core.impl.scheduling.QuartzCronSchedulerProvider;
+import org.apache.felix.hc.core.impl.scheduling.CronJobFactory;
 import org.apache.felix.hc.core.impl.util.HealthCheckFilter;
 import org.apache.felix.hc.core.impl.util.lang.StringUtils;
 import org.osgi.framework.BundleContext;
@@ -72,7 +71,7 @@ public class AsyncHealthCheckExecutor implements ServiceListener {
     HealthCheckExecutorThreadPool healthCheckExecutorThreadPool;
     
     @Reference
-    QuartzCronSchedulerProvider quartzCronSchedulerProvider;
+    CronJobFactory cronJobFactory;
 
     @Activate
     protected final void activate(final ComponentContext componentContext) throws InvalidSyntaxException {
@@ -139,8 +138,8 @@ public class AsyncHealthCheckExecutor implements ServiceListener {
             if (isAsyncCron(descriptor)) {
             
                 try {
-                    healthCheckAsyncJob = new AsyncQuartzCronJob(getAsyncJob(descriptor), quartzCronSchedulerProvider, "job-hc-" + descriptor.getServiceId(), "async-healthchecks", descriptor.getAsyncCronExpression());
-                } catch(ClassNotFoundException|NoClassDefFoundError e) {
+                    healthCheckAsyncJob = cronJobFactory.getAsyncCronJob(getAsyncJob(descriptor), "job-hc-" + descriptor.getServiceId(), "async-healthchecks", descriptor.getAsyncCronExpression());
+                } catch(UnsupportedOperationException e) {
                     LOG.warn("Can not schedule async health check '{}' with cron expression '{}' since quartz library is not on classpath", descriptor.getName(), descriptor.getAsyncCronExpression());
                     return false;
                 }
diff --git a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/monitor/HealthCheckMonitor.java b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/monitor/HealthCheckMonitor.java
index 36ce295..96c9046 100644
--- a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/monitor/HealthCheckMonitor.java
+++ b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/monitor/HealthCheckMonitor.java
@@ -38,8 +38,7 @@ import org.apache.felix.hc.core.impl.executor.CombinedExecutionResult;
 import org.apache.felix.hc.core.impl.executor.HealthCheckExecutorThreadPool;
 import org.apache.felix.hc.core.impl.scheduling.AsyncIntervalJob;
 import org.apache.felix.hc.core.impl.scheduling.AsyncJob;
-import org.apache.felix.hc.core.impl.scheduling.AsyncQuartzCronJob;
-import org.apache.felix.hc.core.impl.scheduling.QuartzCronSchedulerProvider;
+import org.apache.felix.hc.core.impl.scheduling.CronJobFactory;
 import org.apache.felix.hc.core.impl.util.lang.StringUtils;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
@@ -127,7 +126,7 @@ public class HealthCheckMonitor implements Runnable {
     HealthCheckExecutorThreadPool healthCheckExecutorThreadPool;
 
     @Reference
-    QuartzCronSchedulerProvider quartzCronSchedulerProvider;
+    CronJobFactory cronJobFactory;
 
     @Reference
     private EventAdmin eventAdmin;
@@ -173,10 +172,9 @@ public class HealthCheckMonitor implements Runnable {
         this.cronExpression = config.cronExpression();
         if (StringUtils.isNotBlank(cronExpression)) {
             try {
-                monitorJob = new AsyncQuartzCronJob(this, quartzCronSchedulerProvider,
-                        "job-hc-monitor-" + componentContext.getProperties().get(ComponentConstants.COMPONENT_ID),
+                monitorJob = cronJobFactory.getAsyncCronJob(this, "job-hc-monitor-" + componentContext.getProperties().get(ComponentConstants.COMPONENT_ID),
                         "healthcheck-monitor", cronExpression);
-            } catch (ClassNotFoundException e) {
+            } catch (UnsupportedOperationException e) {
                 throw new IllegalArgumentException("Cannot use cron expression " + cronExpression
                         + " while class is not available: " + cronExpression);
             }
diff --git a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncQuartzCronJob.java b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncQuartzCronJob.java
index 43b708d..2eafc29 100644
--- a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncQuartzCronJob.java
+++ b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncQuartzCronJob.java
@@ -33,7 +33,7 @@ import org.quartz.SchedulerException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-/** Runs health checks that are configured with a cron expression for asynchronous execution. 
+/** Async job to be used by async health checks and async monitor. 
  * 
  * This implementation uses quartz to support the cron syntax (which is not supported by executors from standard java java.util.concurrent
  * package) */
@@ -42,16 +42,17 @@ public class AsyncQuartzCronJob extends AsyncJob {
 
     private static final String JOB_DATA_KEY_JOB = "asyncHcJob";
 
-    protected final QuartzCronScheduler quartzCronScheduler;
     private final String id;
     private final String group;
     private final String cronExpression;
 
+    private final Scheduler quartzScheduler;
+
     private JobKey jobKey = null;
 
-    public AsyncQuartzCronJob(Runnable runnable, QuartzCronSchedulerProvider quartzCronSchedulerProvider, String id, String group, String cronExpression) throws ClassNotFoundException {
+    public AsyncQuartzCronJob(Runnable runnable, Scheduler quartzScheduler, String id, String group, String cronExpression) {
         super(runnable);
-        this.quartzCronScheduler = quartzCronSchedulerProvider.getQuartzCronScheduler();
+        this.quartzScheduler = quartzScheduler;
         this.id = id;
         this.group = group;
         this.cronExpression = cronExpression;
@@ -77,13 +78,12 @@ public class AsyncQuartzCronJob extends AsyncJob {
     public boolean schedule() {
 
         try {
-            Scheduler scheduler = quartzCronScheduler.getScheduler();
 
             JobDetail job = getQuartzJobDetail();
             CronTrigger cronTrigger = newTrigger().withSchedule(cronSchedule(cronExpression)).forJob(job)
                     .build();
 
-            scheduler.scheduleJob(job, cronTrigger);
+            quartzScheduler.scheduleJob(job, cronTrigger);
             LOG.info("Scheduled job {} with trigger {}", job, cronTrigger);
             return true;
         } catch (SchedulerException e) {
@@ -95,10 +95,9 @@ public class AsyncQuartzCronJob extends AsyncJob {
 
     @Override
     public boolean unschedule() {
-        Scheduler scheduler = quartzCronScheduler.getScheduler();
         LOG.debug("Unscheduling job {}", jobKey);
         try {
-            scheduler.deleteJob(jobKey);
+            quartzScheduler.deleteJob(jobKey);
             return true;
         } catch (SchedulerException e) {
             LOG.error("Could not unschedule job for " + jobKey + ": " + e, e);
diff --git a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncSimpleCronJob.java b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncSimpleCronJob.java
new file mode 100644
index 0000000..1114fac
--- /dev/null
+++ b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncSimpleCronJob.java
@@ -0,0 +1,38 @@
+/*
+ * 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 SF 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.felix.hc.core.impl.scheduling;
+
+/** Simple cron job implementation without quartz dependency. */
+public class AsyncSimpleCronJob extends AsyncJob {
+
+    public AsyncSimpleCronJob(Runnable runnable, /* some scheduler has to be passed here */ String cronExpression) {
+        super(runnable);
+        throw new UnsupportedOperationException("AsyncSimpleCronJob not yet implemented");
+    }
+
+    @Override
+    public boolean schedule() {
+        throw new UnsupportedOperationException("AsyncSimpleCronJob not yet implemented");
+    }
+
+    @Override
+    public boolean unschedule() {
+        throw new UnsupportedOperationException("AsyncSimpleCronJob not yet implemented");
+    }
+
+}
\ No newline at end of file
diff --git a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/QuartzCronSchedulerProvider.java b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/CronJobFactory.java
similarity index 53%
rename from healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/QuartzCronSchedulerProvider.java
rename to healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/CronJobFactory.java
index fa2afdc..313128c 100644
--- a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/QuartzCronSchedulerProvider.java
+++ b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/CronJobFactory.java
@@ -21,40 +21,58 @@ import org.apache.felix.hc.core.impl.executor.HealthCheckExecutorThreadPool;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Deactivate;
 import org.osgi.service.component.annotations.Reference;
+import org.quartz.SchedulerException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /** Component without direct quartz imports (can always start) that will provide a QuartzCronScheduler on demand. */
-@Component(service = QuartzCronSchedulerProvider.class)
-public class QuartzCronSchedulerProvider {
+@Component(service = CronJobFactory.class)
+public class CronJobFactory {
 
-    private static final Logger LOG = LoggerFactory.getLogger(QuartzCronSchedulerProvider.class);
+    private static final Logger LOG = LoggerFactory.getLogger(CronJobFactory.class);
     private static final String CLASS_FROM_QUARTZ_FRAMEWORK = "org.quartz.CronTrigger";
 
-    private QuartzCronScheduler quartzCronScheduler = null;
-
     @Reference
     HealthCheckExecutorThreadPool healthCheckExecutorThreadPool;
 
-    public synchronized QuartzCronScheduler getQuartzCronScheduler() throws ClassNotFoundException {
-        if (quartzCronScheduler == null) {
-            if (classExists(CLASS_FROM_QUARTZ_FRAMEWORK)) {
-                quartzCronScheduler = new QuartzCronScheduler(healthCheckExecutorThreadPool);
-                LOG.info("Created quartz scheduler health check core bundle");
-            } else {
-                throw new ClassNotFoundException("Class " + CLASS_FROM_QUARTZ_FRAMEWORK
-                        + " was not found (install quartz library into classpath)");
-            }
+    org.quartz.Scheduler quartzScheduler;
+
+    public AsyncJob getAsyncCronJob(Runnable runnable, String id, String group, String cronExpression) {
+
+        if(isQuartzAvailable()) {
+            return new AsyncQuartzCronJob(runnable, getQuartzCronScheduler(), id, group, cronExpression);
+        } else {
+            return new AsyncSimpleCronJob(runnable, cronExpression);
         }
-        return quartzCronScheduler;
+    }
+    
+    private synchronized org.quartz.Scheduler getQuartzCronScheduler() {
+        if (quartzScheduler == null) {
+            QuartzCronSchedulerBuilder quartzCronSchedulerBuilder = new QuartzCronSchedulerBuilder(healthCheckExecutorThreadPool);
+            quartzScheduler = quartzCronSchedulerBuilder.getScheduler();
+            LOG.info("Created quartz scheduler health check core bundle");
+        }
+        return quartzScheduler;
+    }
+
+    
+    public boolean isQuartzAvailable() {
+        return classExists(CLASS_FROM_QUARTZ_FRAMEWORK);
     }
 
     @Deactivate
     protected synchronized void deactivate() {
-        if (quartzCronScheduler != null) {
-            quartzCronScheduler.shutdown();
-            quartzCronScheduler = null;
-            LOG.info("QuartzCronScheduler shutdown");
+        // simpleScheduler follows its own SCR lifecycle
+        
+        if (quartzScheduler != null) { // quartz scheduler needs to be shut down
+            try {
+                quartzScheduler.shutdown();
+                LOG.info("QuartzCronScheduler shutdown");
+            } catch (SchedulerException e) {
+                LOG.info("QuartzCronScheduler shutdown with exception: "+e);
+            } finally {
+               quartzScheduler = null;
+            }
         }
     }
 
diff --git a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/QuartzCronScheduler.java b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/QuartzCronSchedulerBuilder.java
similarity index 87%
rename from healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/QuartzCronScheduler.java
rename to healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/QuartzCronSchedulerBuilder.java
index 8fc6cb7..9ba0f95 100644
--- a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/QuartzCronScheduler.java
+++ b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/QuartzCronSchedulerBuilder.java
@@ -26,14 +26,14 @@ import org.quartz.spi.ThreadPool;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class QuartzCronScheduler {
-    private static final Logger LOG = LoggerFactory.getLogger(QuartzCronScheduler.class);
+public class QuartzCronSchedulerBuilder {
+    private static final Logger LOG = LoggerFactory.getLogger(QuartzCronSchedulerBuilder.class);
 
     private static final String HC_SCHEDULER_NAME = "quartz.hc.scheduler_name";
 
     private Scheduler scheduler;
 
-    public QuartzCronScheduler(HealthCheckExecutorThreadPool healthCheckExecutorThreadPool) {
+    public QuartzCronSchedulerBuilder(HealthCheckExecutorThreadPool healthCheckExecutorThreadPool) {
         try {
             DirectSchedulerFactory schedulerFactory = DirectSchedulerFactory.getInstance();
             ThreadPool threadPool = new QuartzThreadPool(healthCheckExecutorThreadPool);
@@ -46,17 +46,6 @@ public class QuartzCronScheduler {
         }
     }
 
-    public void shutdown() {
-        if (scheduler != null) {
-            try {
-                scheduler.shutdown(false);
-                LOG.debug("Shutdown of quartz scheduler finished: {}", scheduler);
-            } catch (SchedulerException e) {
-                throw new IllegalStateException("Could not shutdown quartz scheduler " + HC_SCHEDULER_NAME, e);
-            }
-        }
-    }
-
     public Scheduler getScheduler() {
         return scheduler;
     }