This is an automated email from the ASF dual-hosted git repository. ghenzler pushed a commit to branch feature/FELIX-6245-condition-service-interfaces-FELIX-6250-healthcheck-monitor in repository https://gitbox.apache.org/repos/asf/felix-dev.git
commit a90b002ec5c4b9a3a5fe5117b373420b01f3f40c Author: georg.henzler <[email protected]> AuthorDate: Sat Mar 28 01:43:50 2020 +0100 FELIX-6250 Refactored interval/quartz jobs of async HCs in order to make them reusable for HealthCheckMonitor --- .gitignore | 1 + .../executor/async/AsyncHealthCheckExecutor.java | 84 +++++++++++++--------- .../impl/executor/async/AsyncHealthCheckJob.java | 68 ------------------ .../AsyncIntervalJob.java} | 28 ++++---- .../felix/hc/core/impl/scheduling/AsyncJob.java | 33 +++++++++ .../AsyncQuartzCronJob.java} | 42 ++++++----- .../async => scheduling}/QuartzCronScheduler.java | 2 +- .../scheduling/QuartzCronSchedulerProvider.java | 68 ++++++++++++++++++ 8 files changed, 193 insertions(+), 133 deletions(-) diff --git a/.gitignore b/.gitignore index ee18842..a03bc09 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ maven-eclipse.xml .idea/ *~ dependency-reduced-pom.xml +.DS_Store \ No newline at end of file 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 ac96df5..e3ecc43 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 @@ -35,7 +35,14 @@ import org.apache.felix.hc.api.execution.HealthCheckMetadata; import org.apache.felix.hc.api.execution.HealthCheckSelector; import org.apache.felix.hc.core.impl.executor.ExecutionResult; import org.apache.felix.hc.core.impl.executor.HealthCheckExecutorThreadPool; +import org.apache.felix.hc.core.impl.executor.HealthCheckFuture; +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.AsyncQuartzCronJob; +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.QuartzCronScheduler; +import org.apache.felix.hc.core.impl.scheduling.QuartzCronSchedulerProvider; import org.apache.felix.hc.core.impl.util.HealthCheckFilter; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; @@ -56,16 +63,17 @@ public class AsyncHealthCheckExecutor implements ServiceListener { private static final Logger LOG = LoggerFactory.getLogger(AsyncHealthCheckExecutor.class); - @Reference - HealthCheckExecutorThreadPool healthCheckExecutorThreadPool; - - private Map<HealthCheckMetadata, ExecutionResult> asyncResultsByDescriptor = new ConcurrentHashMap<HealthCheckMetadata, ExecutionResult>(); + private Map<HealthCheckMetadata, ExecutionResult> asyncResultsByDescriptor = new ConcurrentHashMap<>(); - private Map<HealthCheckMetadata, AsyncHealthCheckJob> registeredJobs = new HashMap<HealthCheckMetadata, AsyncHealthCheckJob>(); + private Map<HealthCheckMetadata, AsyncJob> registeredJobs = new HashMap<>(); private BundleContext bundleContext; - private QuartzCronScheduler quartzCronScheduler = null; + @Reference + HealthCheckExecutorThreadPool healthCheckExecutorThreadPool; + + @Reference + QuartzCronSchedulerProvider quartzCronSchedulerProvider; @Activate protected final void activate(final ComponentContext componentContext) throws InvalidSyntaxException { @@ -95,10 +103,6 @@ public class AsyncHealthCheckExecutor implements ServiceListener { for (HealthCheckMetadata healthCheckDescriptor : new LinkedList<HealthCheckMetadata>(registeredJobs.keySet())) { unscheduleHealthCheck(healthCheckDescriptor); } - - if (quartzCronScheduler != null) { - quartzCronScheduler.shutdown(); - } } @Override @@ -131,24 +135,18 @@ public class AsyncHealthCheckExecutor implements ServiceListener { private boolean scheduleHealthCheck(HealthCheckMetadata descriptor) { try { - AsyncHealthCheckJob healthCheckAsyncJob = null; - + AsyncJob healthCheckAsyncJob = null; + if (isAsyncCron(descriptor)) { - - if (quartzCronScheduler == null) { - if (classExists("org.quartz.CronTrigger")) { - quartzCronScheduler = new QuartzCronScheduler(healthCheckExecutorThreadPool); - LOG.info("Created quartz scheduler for async HC"); - } else { - LOG.warn("Can not schedule async health check '{}' with cron expression '{}' since quartz library is not on classpath", descriptor.getName(), descriptor.getAsyncCronExpression()); - return false; - } + + try { + healthCheckAsyncJob = new AsyncQuartzCronJob(getAsyncJob(descriptor), quartzCronSchedulerProvider, "job-hc-" + descriptor.getServiceId(), "async-healthchecks", descriptor.getAsyncCronExpression()); + } catch(ClassNotFoundException|NoClassDefFoundError 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; } - - healthCheckAsyncJob = new AsyncHealthCheckQuartzCronJob(descriptor, this, bundleContext, quartzCronScheduler); } else if (isAsyncInterval(descriptor)) { - - healthCheckAsyncJob = new AsyncHealthCheckIntervalJob(descriptor, this, bundleContext, healthCheckExecutorThreadPool); + healthCheckAsyncJob = new AsyncIntervalJob(getAsyncJob(descriptor), healthCheckExecutorThreadPool, descriptor.getAsyncIntervalInSec()); } if (healthCheckAsyncJob != null) { @@ -166,13 +164,38 @@ public class AsyncHealthCheckExecutor implements ServiceListener { } + private Runnable getAsyncJob(HealthCheckMetadata descriptor) { + + return new Runnable() { + @Override + public void run() { + LOG.debug("Running job {}", this); + HealthCheckFuture healthCheckFuture = new HealthCheckFuture(descriptor, bundleContext, new Callback() { + + @Override + public void finished(HealthCheckExecutionResult result) { + updateWith(result); + } + }); + + // run future in same thread (as we are already async via scheduler) + healthCheckFuture.run(); + } + + @Override + public String toString() { + return descriptor.toString(); + } + }; + } + private boolean unscheduleHealthCheck(HealthCheckMetadata descriptor) { // here no check for isAsync must be used to ensure previously // scheduled async checks are correctly unscheduled if they have // changed from async to sync. - AsyncHealthCheckJob job = registeredJobs.remove(descriptor); + AsyncJob job = registeredJobs.remove(descriptor); if (job != null) { return job.unschedule(); } else { @@ -250,13 +273,4 @@ public class AsyncHealthCheckExecutor implements ServiceListener { return healthCheckMetadata.getAsyncIntervalInSec() != null && healthCheckMetadata.getAsyncIntervalInSec() > 0L; } - private boolean classExists(String className) { - try { - Class.forName(className); - return true; - } catch (ClassNotFoundException e) { - return false; - } - } - } diff --git a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckJob.java b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckJob.java deleted file mode 100644 index 161d7d4..0000000 --- a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckJob.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.executor.async; - -import org.apache.felix.hc.api.execution.HealthCheckExecutionResult; -import org.apache.felix.hc.api.execution.HealthCheckMetadata; -import org.apache.felix.hc.core.impl.executor.HealthCheckFuture; -import org.apache.felix.hc.core.impl.executor.HealthCheckFuture.Callback; -import org.osgi.framework.BundleContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** Abstract class for async execution variants cron/interval. */ -public abstract class AsyncHealthCheckJob implements Runnable { - private static final Logger LOG = LoggerFactory.getLogger(AsyncHealthCheckJob.class); - - protected final HealthCheckMetadata healthCheckDescriptor; - protected final AsyncHealthCheckExecutor asyncHealthCheckExecutor; - protected final BundleContext bundleContext; - - public AsyncHealthCheckJob(HealthCheckMetadata healthCheckDescriptor, AsyncHealthCheckExecutor asyncHealthCheckExecutor, - BundleContext bundleContext) { - this.healthCheckDescriptor = healthCheckDescriptor; - this.asyncHealthCheckExecutor = asyncHealthCheckExecutor; - this.bundleContext = bundleContext; - } - - @Override - public void run() { - - LOG.debug("Running job {}", this); - HealthCheckFuture healthCheckFuture = new HealthCheckFuture(healthCheckDescriptor, bundleContext, new Callback() { - - @Override - public void finished(HealthCheckExecutionResult result) { - asyncHealthCheckExecutor.updateWith(result); - } - }); - - // run future in same thread (as we are already async via scheduler) - healthCheckFuture.run(); - - } - - public abstract boolean schedule(); - - public abstract boolean unschedule(); - - @Override - public String toString() { - return "[Async job for " + this.healthCheckDescriptor + "]"; - } -} \ No newline at end of file diff --git a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckIntervalJob.java b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncIntervalJob.java similarity index 67% rename from healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckIntervalJob.java rename to healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncIntervalJob.java index 3561382..a5758b4 100644 --- a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckIntervalJob.java +++ b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncIntervalJob.java @@ -15,32 +15,31 @@ * 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.executor.async; +package org.apache.felix.hc.core.impl.scheduling; import java.util.concurrent.ScheduledFuture; -import org.apache.felix.hc.api.execution.HealthCheckMetadata; import org.apache.felix.hc.core.impl.executor.HealthCheckExecutorThreadPool; -import org.osgi.framework.BundleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** Runs health checks that are configured with an interval (ScheduledThreadPoolExecutor.scheduleAtFixedRate()) for asynchronous execution. */ -public class AsyncHealthCheckIntervalJob extends AsyncHealthCheckJob implements Runnable { - private static final Logger LOG = LoggerFactory.getLogger(AsyncHealthCheckExecutor.class); +public class AsyncIntervalJob extends AsyncJob { + private static final Logger LOG = LoggerFactory.getLogger(AsyncIntervalJob.class); private final HealthCheckExecutorThreadPool healthCheckExecutorThreadPool; + private final Long asyncIntervalInSec; + private ScheduledFuture<?> scheduleFuture = null; - public AsyncHealthCheckIntervalJob(HealthCheckMetadata healthCheckDescriptor, AsyncHealthCheckExecutor asyncHealthCheckExecutor, - BundleContext bundleContext, HealthCheckExecutorThreadPool healthCheckExecutorThreadPool) { - super(healthCheckDescriptor, asyncHealthCheckExecutor, bundleContext); + public AsyncIntervalJob(Runnable runnable, HealthCheckExecutorThreadPool healthCheckExecutorThreadPool, Long asyncIntervalInSec) { + super(runnable); this.healthCheckExecutorThreadPool = healthCheckExecutorThreadPool; + this.asyncIntervalInSec = asyncIntervalInSec; } public boolean schedule() { - Long asyncIntervalInSec = healthCheckDescriptor.getAsyncIntervalInSec(); - scheduleFuture = healthCheckExecutorThreadPool.scheduleAtFixedRate(this, asyncIntervalInSec); + scheduleFuture = healthCheckExecutorThreadPool.scheduleAtFixedRate(runnable, asyncIntervalInSec); LOG.info("Scheduled job {} for execution every {}sec", this, asyncIntervalInSec); return true; } @@ -49,12 +48,17 @@ public class AsyncHealthCheckIntervalJob extends AsyncHealthCheckJob implements public boolean unschedule() { if (scheduleFuture != null) { - LOG.debug("Unscheduling async job for {}", healthCheckDescriptor); + LOG.debug("Unscheduling async job for {}", runnable); return scheduleFuture.cancel(false); } else { - LOG.debug("No scheduled future for {} exists", healthCheckDescriptor); + LOG.debug("No scheduled future for {} exists", runnable); return false; } } + + @Override + public String toString() { + return "[Async interval job for " + runnable + "]"; + } } \ No newline at end of file diff --git a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncJob.java b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncJob.java new file mode 100644 index 0000000..18d5c68 --- /dev/null +++ b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncJob.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 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; + +/** Abstract class for async scheduling variants cron/interval. */ +public abstract class AsyncJob { + + protected final Runnable runnable; + + public AsyncJob(Runnable runnable) { + this.runnable = runnable; + } + + public abstract boolean schedule(); + + public abstract boolean unschedule(); + +} \ No newline at end of file diff --git a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckQuartzCronJob.java b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncQuartzCronJob.java similarity index 72% rename from healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckQuartzCronJob.java rename to healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncQuartzCronJob.java index fed885c..15317e0 100644 --- a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckQuartzCronJob.java +++ b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncQuartzCronJob.java @@ -15,14 +15,12 @@ * 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.executor.async; +package org.apache.felix.hc.core.impl.scheduling; import static org.quartz.CronScheduleBuilder.cronSchedule; import static org.quartz.JobBuilder.newJob; import static org.quartz.TriggerBuilder.newTrigger; -import org.apache.felix.hc.api.execution.HealthCheckMetadata; -import org.osgi.framework.BundleContext; import org.quartz.CronTrigger; import org.quartz.Job; import org.quartz.JobDataMap; @@ -39,18 +37,24 @@ import org.slf4j.LoggerFactory; * * This implementation uses quartz to support the cron syntax (which is not supported by executors from standard java java.util.concurrent * package) */ -public class AsyncHealthCheckQuartzCronJob extends AsyncHealthCheckJob implements Runnable { - private static final Logger LOG = LoggerFactory.getLogger(AsyncHealthCheckExecutor.class); +public class AsyncQuartzCronJob extends AsyncJob { + private static final Logger LOG = LoggerFactory.getLogger(AsyncQuartzCronJob.class); 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 JobKey jobKey = null; - public AsyncHealthCheckQuartzCronJob(HealthCheckMetadata healthCheckDescriptor, AsyncHealthCheckExecutor asyncHealthCheckExecutor, - BundleContext bundleContext, QuartzCronScheduler quartzScheduler) { - super(healthCheckDescriptor, asyncHealthCheckExecutor, bundleContext); - this.quartzCronScheduler = quartzScheduler; + public AsyncQuartzCronJob(Runnable runnable, QuartzCronSchedulerProvider quartzCronSchedulerProvider, String id, String group, String cronExpression) throws ClassNotFoundException { + super(runnable); + this.quartzCronScheduler = quartzCronSchedulerProvider.getQuartzCronScheduler(); + this.id = id; + this.group = group; + this.cronExpression = cronExpression; } public JobKey getJobKey() { @@ -59,10 +63,10 @@ public class AsyncHealthCheckQuartzCronJob extends AsyncHealthCheckJob implement private JobDetail getQuartzJobDetail() { JobDataMap jobData = new JobDataMap(); - jobData.put(JOB_DATA_KEY_JOB, this); + jobData.put(JOB_DATA_KEY_JOB, runnable); - JobDetail job = newJob(AsyncHealthCheckQuartzCronJob.QuartzJob.class).setJobData(jobData) - .withIdentity("job-hc-" + healthCheckDescriptor.getServiceId(), "async-healthchecks") + JobDetail job = newJob(AsyncQuartzCronJob.QuartzJob.class).setJobData(jobData) + .withIdentity(id, group) .build(); jobKey = job.getKey(); @@ -76,14 +80,14 @@ public class AsyncHealthCheckQuartzCronJob extends AsyncHealthCheckJob implement Scheduler scheduler = quartzCronScheduler.getScheduler(); JobDetail job = getQuartzJobDetail(); - CronTrigger cronTrigger = newTrigger().withSchedule(cronSchedule(healthCheckDescriptor.getAsyncCronExpression())).forJob(job) + CronTrigger cronTrigger = newTrigger().withSchedule(cronSchedule(cronExpression)).forJob(job) .build(); scheduler.scheduleJob(job, cronTrigger); LOG.info("Scheduled job {} with trigger {}", job, cronTrigger); return true; } catch (SchedulerException e) { - LOG.error("Could not schedule job for " + healthCheckDescriptor + ": " + e, e); + LOG.error("Could not schedule job for " + runnable + ": " + e, e); return false; } @@ -102,15 +106,19 @@ public class AsyncHealthCheckQuartzCronJob extends AsyncHealthCheckJob implement } } + @Override + public String toString() { + return "[Async quartz job for " + runnable + "]"; + } + // quartz forces to pass in a class object (and not an instance), hence this helper class is needed public static class QuartzJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { - AsyncHealthCheckQuartzCronJob hc = (AsyncHealthCheckQuartzCronJob) context.getJobDetail().getJobDataMap().get(JOB_DATA_KEY_JOB); - hc.run(); + Runnable ayncJob = (Runnable) context.getJobDetail().getJobDataMap().get(JOB_DATA_KEY_JOB); + ayncJob.run(); } - } } \ No newline at end of file diff --git a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/QuartzCronScheduler.java b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/QuartzCronScheduler.java similarity index 98% rename from healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/QuartzCronScheduler.java rename to healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/QuartzCronScheduler.java index c43b97e..8fc6cb7 100644 --- a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/QuartzCronScheduler.java +++ b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/QuartzCronScheduler.java @@ -15,7 +15,7 @@ * 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.executor.async; +package org.apache.felix.hc.core.impl.scheduling; import org.apache.felix.hc.core.impl.executor.HealthCheckExecutorThreadPool; import org.quartz.Scheduler; 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/QuartzCronSchedulerProvider.java new file mode 100644 index 0000000..70b4f8e --- /dev/null +++ b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/QuartzCronSchedulerProvider.java @@ -0,0 +1,68 @@ +/* + * 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; + +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.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 { + + private static final Logger LOG = LoggerFactory.getLogger(QuartzCronSchedulerProvider.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)"); + } + } + return quartzCronScheduler; + } + + @Deactivate + protected synchronized void deactivate() { + if (quartzCronScheduler != null) { + quartzCronScheduler.shutdown(); + quartzCronScheduler = null; + LOG.info("QuartzCronScheduler shutdown"); + } + } + + private boolean classExists(String className) { + try { + Class.forName(className); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } +}
