1.8. Scheduling#
Zamanlanmış görevler tanımlanmasını sağlayan bileşendir. Uygulama cluster özelliklerini sağlar (distributable). Quartz library'si kulanılmaktadır.
Konfigurasyon#
Gradle Bağımlılıkları
Cluster Konfigürasyonları
Veritabanında cluster olan bir uygulamadır. Quartz tabloları manuel ya da liquibase ile initialize edilebilir.
spring:
quartz:
scheduler-name: ${spring.application.name}
auto-startup: true
startup-delay: 2s
overwrite-existing-jobs: true
job-store-type: jdbc
liquibase:
parameters:
quartz-jdbc-job-store-schema: ${hvl.scheduling.quartz.jdbc-job-store.schema-name}
quartz-jdbc-job-store-table-prefix: ${hvl.scheduling.quartz.jdbc-job-store.table-prefix}
Çevre Değişkenleri
Cloud profili olarak "hvl-scheduling" verilerek, ya da bootstrap.yml dosyasına yapılan aşağıdaki tanımlamalarla çevre değişkenleri yönetilebilir.
-
QUARTZ_JDBC_JOB_STORE_SCHEMA (schema-name): Scheduler'ın kullandığı şema adıdır (default değerini hibernate'den alınır).
-
"table-prefix": Quartz tablolarına koyulacak ön ektir (default değeri "qrz_"dır).
ÖNEMLİ NOT: Varsayılan olarak her uygulamanın default şemasında quartz tabloları oluşmaktadır. Bazı durumlarda quartz tablolarının tek şemada olması ya da ortak scheduler kullanımları gibi durumlar için bu property'ler yararlıdır. Örneğin; "oauth", "report" ve "bpmn" şemalarımız olsun. Bu şemalarda quartz tabloları olması istenmeyebilir. Bu durumda "schedule" şema ismi tanımlanır. "oauth", "report" ve "bpmn" uygulamalarının quartz scheduler'ların olduğunu varsayalım. Bu uygulamalar için ortak şema kullanmak istediğimizde yukarıdaki "schema-name" property'si değeri kullanılır.
ÖNEMLİ NOT: Varsayılan olarak her uygulamanın içerisine quartz dahil edildiğinde otokonfigurasyon tarafından uygulamanın adı ile tanımlanmış bir scheduler oluşmaktadır. Yani uygulama adı; "scheduler name"'dir. Sebebi; ortak bir arayüzden uygulamadaki planlanmış görevler yönetilmek istendiğinde, uygulama bazlı ayrı yapılmasının sağlanmasıdır.
Kullanım#
Bileşen iki farklı şekilde kullanılabilir.
-
@HvlDistributableScheduled anotasyonu metodun üzerine yazılır ve bu anotasyonun property'leri örnekte görüldüğü gibi doldururulur.
jobName: Quartz job adıdır.
jobGroupName: Quartz job grup adıdır.
jobTriggers: Quartz job trigger tanımıdır.
triggerType: Quartz job'ın trigger tipidir.
triggerExp: Quartz job'ın belirlenen trigger tipine uygun expression değeridir.
package tr.com.havelsan.javarch.samples.scheduling;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import tr.com.havelsan.javarch.samples.scheduling.configuration.HvlSchedulingConfiguration;
import tr.com.havelsan.javarch.scheduling.annotation.HvlDistributableScheduled;
import tr.com.havelsan.javarch.scheduling.annotation.HvlJobTrigger;
import tr.com.havelsan.javarch.scheduling.annotation.HvlJobTriggerType;
/**
* @author javarch
*/
@SpringBootApplication(scanBasePackageClasses = HvlSchedulingConfiguration.class)
public class HvlSchedulingServerApplication {
public static void main(String[] args) {
final ConfigurableApplicationContext configurableApplicationContext
= SpringApplication.run(new Class[]{HvlSchedulingServerApplication.class}, args);
}
@HvlDistributableScheduled(
jobName = "sample-job",
jobGroupName = "sample-job-group",
jobTriggers = @HvlJobTrigger(
triggerType = HvlJobTriggerType.CRON,
triggerExp = "0 15 10 * * ?"
)
)
private static void scheduledWithCron(ConfigurableApplicationContext configurableApplicationContext) {
System.out.println("scheduledWithCron triggered.");
}
@HvlDistributableScheduled(
jobName = "sample-job",
jobGroupName = "sample-job-group",
jobTriggers = @HvlJobTrigger(
triggerType = HvlJobTriggerType.FIXED_RATE,
triggerExp = "PT45M"
)
)
private static void scheduledWithSecond(ConfigurableApplicationContext configurableApplicationContext) {
System.out.println("scheduledWithSecond triggered.");
}
}
- Bir diğer kullanım ise; HvlQuartzExecutableJob sınıfını extend eden bir class oluşturmaktır.
package tr.com.havelsan.javarch.samples.scheduling.job;
import org.quartz.JobExecutionContext;
import tr.com.havelsan.javarch.scheduling.quartz.job.HvlQuartzExecutableJob;
import java.util.Set;
public class SampleJob extends HvlQuartzExecutableJob {
@Override
protected Integer jobExecutionMaxRetryCount() {
return 3;
}
@Override
protected Set<Class<? extends Throwable>> whenJobExecutionRetry() {
return Set.of();
}
@Override
protected void executeJobInstance(JobExecutionContext jobExecutionContext) {
System.err.println("job executed.");
}
}
package tr.com.havelsan.javarch.samples.scheduling.configuration;
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import tr.com.havelsan.javarch.configuration.HvlBaseConfiguration;
import tr.com.havelsan.javarch.samples.scheduling.configuration.constant.HvlSchedulingConfigurationConstant;
import tr.com.havelsan.javarch.samples.scheduling.job.SampleJob;
/**
* @author javarch
*/
@Configuration
@ComponentScan(basePackages = {HvlSchedulingConfigurationConstant.BASE_PACKAGE})
public class HvlSchedulingConfiguration extends HvlBaseConfiguration {
@Bean
public JobDetail sampleJobDetail() {
return JobBuilder.newJob(SampleJob.class)
.storeDurably()
.build();
}
@Bean
public Trigger sampleTrigger() {
return TriggerBuilder.newTrigger()
.forJob(sampleJobDetail())
.withIdentity("triggerName", "group1")
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(10)
.repeatForever())
.build();
}
@Bean
public SchedulerFactoryBean schedulerFactory(Trigger sampleTrigger, JobDetail sampleJobDetail) {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setJobDetails(sampleJobDetail);
schedulerFactoryBean.setTriggers(sampleTrigger);
return schedulerFactoryBean;
}
}