SpringQuartz etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
SpringQuartz etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

29 Eylül 2023 Cuma

SpringQuartz @DisallowConcurrentExecution Anotasyonu

Giriş
Şu satırı dahil ederiz
import  org.quartz.DisallowConcurrentExecution;
Örnek
Şöyle yaparız
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

@DisallowConcurrentExecution
public class MyQuartzJob implements Job {
  @Override
  public void execute(JobExecutionContext context) 
  throws JobExecutionException {
    // Your job logic here
  }
}
Açıklaması şöyle
Quartz provides built-in support for locking jobs to prevent concurrent executions. You can set the @DisallowConcurrentExecution annotation on your job classes to ensure that only one instance of a job runs at a time

By adding @DisallowConcurrentExecution, Quartz will automatically ensure that a job instance is locked while it's running, preventing concurrent executions of the same job.


Örnek
Açıklaması şöyle
In the SampleCronJob I have used a annotation @DisallowConcurrentExecution once this is added to a job and if we have multiple scheduler instance are running concurrently this job will not be executed by multiple schedulers concurrently.
Şöyle yaparız
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

@DisallowConcurrentExecution
public class SampleCronJob extends QuartzJobBean {
  @Override
  protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
    ...
  }
}

SpringQuartz SchedulerFactoryBean Sınıfı

Giriş
Şu satırı dahil ederiz
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
Örnek
Şöyle yaparız
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

@Configuration
public class QuartzConfig {
  @Bean
  public SchedulerFactoryBean schedulerFactoryBean() {
    SchedulerFactoryBean factory = new SchedulerFactoryBean();
    factory.setJobFactory(new SpringBeanJobFactory());
    factory.setDataSource(dataSource); // Inject your data source here
    factory.setQuartzProperties(quartzProperties());
    factory.setOverwriteExistingJobs(true);
    factory.setWaitForJobsToCompleteOnShutdown(true);
    return factory;
  }

  // Configure Quartz properties (e.g., thread count, clustering, etc.)
  private Properties quartzProperties() {
    Properties properties = new Properties();
    properties.setProperty("org.quartz.scheduler.instanceName", "MyScheduler");
    properties.setProperty("org.quartz.scheduler.instanceId", "AUTO");
    // Set the number of worker threads
    properties.setProperty("org.quartz.threadPool.threadCount", "5"); 
    properties.setProperty("org.quartz.jobStore.isClustered", "true");
    // Interval for cluster node check-in
    properties.setProperty("org.quartz.jobStore.clusterCheckinInterval", "2000"); 
    properties.setProperty("org.quartz.jobStore.class",
      "org.quartz.impl.jdbcjobstore.JobStoreTX");
    properties.setProperty("org.quartz.jobStore.driverDelegateClass",
      "org.quartz.impl.jdbcjobstore.StdJDBCDelegate");
    properties.setProperty("org.quartz.jobStore.tablePrefix", "QRTZ_");
    return properties;
  }
}


13 Haziran 2023 Salı

SpringQuartz Kullanımı Job Yaratma

Giriş
Açıklaması şöyle
Job — An interface to be implemented by components that we wish to have executed. It has a single method called execute() on which we need to provide the details to be performed by the Job
Job iki şekilde kodlanabilir
1. Quartz projesinin Job arayüzünden kalıtılır
2. Spring' ait QuartzJobBean sınıfından  kalıtılır

Job Arayüzü
Örnek
Şöyle yaparız
public class FileDeletionJob implements Job {

  @Override
  public void execute(JobExecutionContext jobExecutionContext)
     throws JobExecutionException {
    String regex = jobExecutionContext.getJobDetail()
      .getJobDataMap()
      .getString("regex");
    File folder = new File(jobExecutionContext.getJobDetail()
                                              .getJobDataMap()
                                              .getString("path"));
    File[] files = folder.listFiles();

    Function<File, Boolean> regexMatcher = (file) -> Pattern.compile(regex)
      .matcher(file.getName()).find();

    System.out.println("#####Deleting Files#####");
    Arrays.stream(files).filter(regexMatcher::apply)
      .peek(System.out::println)
      .forEach(File::delete);
    System.out.println("#####Done#####");
  }
}
2. Spring QuartzJobBean Sınıfı
Açıklaması şöyle
Spring Boot provides a wrapper around Quartz Scheduler’s Job interface called QuartzJobBean. This allows you to create Quartz Jobs as Spring beans where you can autowire other beans.
Örnek
Şöyle yaparız
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.springframework.scheduling.quartz.QuartzJobBean;

@Component
public class EmailJob extends QuartzJobBean {

  @Override
  protected void executeInternal(JobExecutionContext jobExecutionContext)
throws JobExecutionException {
    logger.info("Executing Job with key {}", jobExecutionContext.getJobDetail().getKey());
    JobDataMap jobDataMap = jobExecutionContext.getMergedJobDataMap();
    ...
  }
}


SpringQuartz Veritabanı

Giriş
Normalde tabloları Quartz'ın kendisini yaratmasında fayda var. Ancak biz kendimiz yapmak istiyorsak şöyle yaparız
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);
FIRED_TRIGGERS  Tablosu
Her çalışan Job bu tabloya bir kayıt atar. İş bitince de siler.



1 Şubat 2021 Pazartesi

SpringQuartz application.properties Ayarları

jobStore Alanı
İki tane alan mecburi. Açıklamalar burada
1. org.quartz.jobStore.dataSource
1. org.quartz.jobStore.driverDelegateClass

1. jobStore .dataSource
Örnek
Şöyle yaparız
spring.quartz.properties.org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
spring.quartz.properties.org.quartz.jobStore.dataSource=CityTasksQuartzDS
Örnek
Şöyle yaparız
##Server Port
server.port = 8099

## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url = jdbc:postgresql://localhost:5432/scheduler
spring.datasource.username = postgres
spring.datasource.password = 

## QuartzProperties
spring.quartz.job-store-type = jdbc
spring.quartz.jdbc.initialize-schema = never
spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
spring.quartz.properties.org.quartz.threadPool.threadCount = 5

2. jobStore .driverDelegateClass
Açıklaması şöyle
Adopt the driverDelegateClass to your database platform — just check the classes in the package org.quarzt.impl.jdbcjobstore to choose from.
Örnek - PostgreSQLDelegate
Şöyle yaparız
spring:
  quartz:
    job-store-type: jdbc
    jdbc:
      initialize-schema: never
    startup-delay: 60s
    properties:
       org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
store-type Alanı
MEMORY veya JDBC seçilebilir.  Açıklaması şöyle
Quartz comes with its own in-built JobStores, and if you need you can create your own by implementing org.quartz.spi.JobStore interface. In spring-boot quartz provides two JobStores

MEMORY— It keeps all of its data in RAM so once the application ends or crashes all the scheduling information is lost. Since it keeps its data in RAM, it is very fast and simple to configure

JDBC — JDBC JobStore keeps all of its data in a database via JDBC. Since it relies on database, configuration is a bit complicated and certainly is not as fast as RAM JobStore
store-type=JDBC 
JDBC kullanacaksak bir DataSource tanımlı olmalıdır. Açıklaması şöyle
If you need to manage jobs on your own and modify them time to time without effecting the up-time of your application you should move to the JDBC job store. You can run clustered or non-clustered scheduler service when using the JDBC job store.
Örnek - jdbc
Şöyle yaparız
spring.quartz.job-store-type=jdbc
spring.quartz.jdbc.initialize-schema=never
Örnek - jdbc
Şöyle yaparız. Burada datasource tanımı da var
spring.datasource.platform=org.hibernate.dialect.MySQL5Dialect
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/quartz_demo_db
spring.datasource.username=root
spring.datasource.password=admin
spring.jpa.open-in-view=false
spring.jpa.show-sql=true

spring.quartz.job-store-type=jdbc
spring.quartz.jdbc.initialize-schema=never
threadpool Alanı
Örnek
Şöyle yaparız
spring.quartz.job-store-type = jdbc
spring.quartz.properties.org.quartz.threadPool.threadCount = 5
instanceId Alanı
Açıklaması şöyle
Each Quartz Scheduler must has a unique ID. The value can be any string but must be unique for all schedulers. If we need we can AUTO generate this id by adding the property
Örnek
Şöyle yaparız
#QUARTZ CONFIGS
spring.quartz.job-store-type=jdbc
spring.quartz.jdbc.initialize-schema=never

spring.quartz.properties.org.quartz.scheduler.instanceName=quartz-demo-app
spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO
spring.quartz.properties.org.quartz.scheduler.instanceIdGenerator.class=com.helixz.quartz.demo.component.CustomQuartzInstanceIdGenerator
spring.quartz.properties.org.quartz.threadPool.threadCount=20
spring.quartz.properties.org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
spring.quartz.properties.org.quartz.jobStore.useProperties=true
spring.quartz.properties.org.quartz.jobStore.misfireThreshold=60000
spring.quartz.properties.org.quartz.jobStore.tablePrefix=qrtz_
spring.quartz.properties.org.quartz.jobStore.isClustered=true
spring.quartz.properties.org.quartz.plugin.shutdownHook.class=org.quartz.plugins.management.ShutdownHookPlugin
spring.quartz.properties.org.quartz.plugin.shutdownHook.cleanShutdown=TRUE
quartz.properties Dosyası
Eğer tüm ayarları application.properties dosyasına doldurmak istemiyorsak quartz.properties dosyası da kullanılabilir.
Örnek
Şöyle yaparız
org.quartz.scheduler.instanceName=sample
org.quartz.scheduler.instanceId=AUTO
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.context.key.QuartzTopic=QuartzProperties
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.isClustered=true

org.quartz.jobStore.dataSource=sample

org.quartz.dataSource.sample.provider=hikaricp
org.quartz.dataSource.sample.URL = jdbc:h2:mem:test;MODE=MySQL
org.quartz.dataSource.sample.driver = org.h2.Driver
serverTimezone=UTC&characterEncoding=UTF-8
org.quartz.dataSource.sample.user = sa