1 Şubat 2021 Pazartesi

SpringQuartz Kullanımı

Giriş
Spring'in kendi scheduler projesi de var. SpringScheduling Kullanımı yazısına bakabilirsiniz. Bu projeyle @Scheduled anotasyonu kullanılabilir. Ancak dinamik olarak bir işi zamanlamak etmek daha zor. 

Quartz dinamik olarak iş zamanlamak için işe yarıyor. 
Ayrıca JobPersistence'ın şu faydası var
It comes with JobPersistence support that can be extremely beneficial for failed jobs as well as reporting purposes.
JobPersistence için bir açıklama şöyle. Yani gelecekte çalışacak bir iş DB'ye yazıldığı için kaybolmuyor
... among our use cases there were actions involving money transfers, such as automatic refunds after several days, and we couldn’t afford to lose any of them in the case of any downtime. We wanted to allow retries and to be able to persist the scheduled messages, ...

Quartz works really well for us, and we have had no significant problems with it in production.
Maven
Şu satırı dahil ederiz
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
veya şu satırı dahil ederiz
<dependency>
 <groupId>org.quartz-scheduler</groupId>
 <artifactId>quartz</artifactId>
 <version>${lasted.version}</version>
</dependency>

Sınıflar
Şeklen şöyle
Kavramlar
Kavramlar şöyle
1. Scheduler 
2 SchedulerFactory
3. Scheduler Repository
4. Job : SpringQuartz Kullanımı Job Yaratma yazısına bakabilirsiniz
5. JobDetail 
6. JobBuilder
7. Trigger : SpringQuartz Kullanımı Trigger Yaratma yazısına bakabilirsiniz
8. TriggerBuilder
9. ThreadPool
10. WorkerThread
11. JobStore
12. DataSources
13 TriggerListeners 
14. SchedulerListeners
14. Eğer dağıtık ortamda kullanacak Job sınıfı üzerinde @DisallowConcurrentExecution anotasyonu kullanılır

org.quartz.Scheduler  Arayüzü
Bu arayüzün en önemli özelliği şöyle
The Quartz Scheduler includes many enterprise-class features, such as support for JTA transactions and clustering.
1. Spring @Scheduled Anotasyonu İle
Bu yöntemi hiç denemedim emin değilim.

Örnek
Şöyle yaparız
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class JobScheduler {
  @Autowired
  private Scheduler scheduler;

  /**
   * Define your cron expression, 
   * better if it is on properties configurations
   */
  @Scheduled(cron = "0 0/5 * * * ?")
  public void scheduleJob() {
    // Schedule your Quartz job here using the Scheduler
  }
}

2. Scheduler Sınıfının scheduled() metodu çağrılır
org.quartz.Scheduler nesnesi Spring projesine ait SchedulerFactoryBean tarafından yaratılır. Açıklaması şöyle
Spring Boot has built-in support for Quartz. It automatically creates a Quartz Scheduler bean with the configuration that we supplied in the application.properties file. That’s why we could directly inject the Scheduler in the controller.
Örnek
Şöyle yaparızorg.quartz.Trigger ve org.quartz.JobDetail nesneleri yaratılıyor
@RestController
public class EmailJobSchedulerController {

  @Autowired
  private Scheduler scheduler;
  
  @PostMapping("/scheduleEmail")
  public ResponseEntity<ScheduleEmailResponse> scheduleEmail(@Valid @RequestBody
ScheduleEmailRequest scheduleEmailRequest) {
    try {
      ZonedDateTime dateTime = ... //işin ne zaman çalışacağı
      JobDetail jobDetail = ... //işi çalıştıracak bean
      Trigger trigger = ...;
      scheduler.scheduleJob(jobDetail, trigger);
      ScheduleEmailResponse scheduleEmailResponse = new ScheduleEmailResponse(true,
        jobDetail.getKey().getName(), jobDetail.getKey().getGroup(), "Email Scheduled");
      return ResponseEntity.ok(scheduleEmailResponse);
    } catch (SchedulerException ex) {
      ...
    }
  }
}
Örnek
schedule() metodunu çağırmadan önce iş zaten mevcut mu diye kontrol etmek isteyebiliriz. Şöyle yaparız
Scheduler scheduler = ...
JobDetail jobDetail = ...
if (!scheduler.checkExists(jobDetail.getKey())) {
  ...
  Trigger trigger = ...;
  scheduler.scheduleJob(jobDetail, trigger);
}
Örnek - Tam Çalışan 
Elimizde şöyle bir servis olsun
@Service
public class EmailService {
  @Autowired
  private JavaMailSender emailSender;

  public void sendSimpleMessage(String to, String subject, String text) {
    SimpleMailMessage message = new SimpleMailMessage(); 
    message.setTo(to); 
    message.setSubject(subject); 
    message.setText(text);
    emailSender.send(message);
  }
}
Bir Job tanımlamak için şöyle yaparız
public class EmailJob extends QuartzJobBean {
  @Autowired
  private EmailService emailService;
  @Override
  protected void executeInternal(JobExecutionContext context) 
  throws JobExecutionException {
    emailService.sendSimpleMessage("your-email@domain.com", 
      "Hey, don't forget!", "This is your friendly reminder.");
  }
}

Job'ı tetiklemek için şöyle yaparız. Burada sadece Trigger bean yaratılıyor. O da otomatik olarak schedule edilir
@Configuration
public class EmailJobScheduler {
  @Autowired
  private ApplicationContext applicationContext;
  @Bean
  public JobDetail jobDetail() {
    JobDataMap jobDataMap = new JobDataMap();
    jobDataMap.put("emailService", applicationContext.getBean(EmailService.class));
    return JobBuilder.newJob(EmailJob.class)
      .withIdentity("emailJob")
      .usingJobData(jobDataMap)
      .storeDurably()
      .build();
  }
  @Bean
  public Trigger trigger(JobDetail jobDetail) {
    SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
      .withIntervalInSeconds(60)
      .repeatForever();
    return TriggerBuilder.newTrigger()
      .forJob(jobDetail)
      .withIdentity("emailTrigger")
      .withSchedule(scheduleBuilder)
      .build();
  }
}



Hiç yorum yok:

Yorum Gönder