220830 오늘의 배움

2022. 8. 31. 10:02오늘의 배움

와 문서읽고 공부하니깐, 정리할 틈이 없다..


오늘의 배움

 

the Quartz Job Scheduling Library
Quartz is a richly featured, open source job scheduling library that can be integrated within virtually any Java application.

https://www.quartz-scheduler.org/overview/

프로젝트에서  2.2.3 을 쓰는데 해당 버전 doc 이 없어서 (웹사이트 re-working 중이라고 한다..)

2.2.2 를 참고하고 있다.

quick start guide 보고, tutorials 보는 중...

 

Why are Jobs AND Triggers separated?

왜 하나로 합치지 않고, job이랑 trigger를 분리했을까?

For example, Jobs can be created and stored in the job scheduler independent of a trigger, and many triggers can be associated with the same job. Another benefit of this loose-coupling is the ability to configure jobs that remain in the scheduler after their associated triggers have expired, so that that it can be rescheduled later, without having to re-define it. It also allows you to modify or replace a trigger without having to re-define its associated job.

 

TRIGGER

SimpleTrigger is handy if you need ‘one-shot’ execution (just single execution of a job
at a given moment in time), or if you need to fire a job at a given time, and have it repeat N times,
with a delay of T between executions.
특정 시점에 딱 한번만 실행하거나, 주어진 시간동안 n번 t 간격으로 실행할 때


CronTrigger is useful if you wish to have triggering based on calendar-like schedules -
such as “every Friday, at noon” or “at 10:15 on the 10th day of every month.”
달력에 적어둘 것 같은 스케쥴 수행 시에 사용 (every ... kind of jobs)

 

Identities

Jobs and Triggers are given identifying keys as they are registered with the Quartz scheduler. The keys of Jobs and Triggers (JobKey and TriggerKey) allow them to be placed into ‘groups’ which can be useful for organizing your jobs and triggers into categories such as “reporting jobs” and “maintenance jobs”. The name portion of the key of a job or trigger must be unique within the group - or in other words, the complete key (or identifier) of a job or trigger is the compound of the name and group.

job하고 trigfger를 key로 스케쥴러에 등록한다. key 값으로 groupping 가능. 카테고리로 묶어서 사용가능하게 되는 것이다.

각 key 값의 name 은 (name:value) group 내에서 unique 해야 함.

결과적으로, 완성된 key ( 또는 identifier ) 는 key name이랑 group 을 합친 것이 된다.

 

More About Jobs and Job Details

While a job class that you implement has the code that knows how to do the actual work of the particular type of job, Quartz needs to be informed about various attributes that you may wish an instance of that job to have. This is done via the JobDetail class, which was mentioned briefly in the previous section.(this is lesson 3)

job 클래스가 특정 job 이 어떤 일을 한다는 걸 알리는 반면에,

jobDetail 클래스는 그 job 이 갖고 있어야 하는 attributes 를 알려준다.(관련 속성!)

see below:

JobDetail job = newJob(HelloJob.class) // HelloJob 이라는 Job interface를 implements 한 class
      .withIdentity("myJob", "group1") // name "myJob", group "group1"
      .build(); // build the JobDetail

이 JobDetail job 이라는 instance 는 스케쥴러에게 주게 된다.

 

Notice that we give the scheduler a JobDetail instance, and that it knows the type of job to be executed by simply providing the job’s class as we build the JobDetail. Each (and every) time the scheduler executes the job, it creates a new instance of the class before calling its execute(..) method.

위의 예시 참고: Job class 만든 걸(implements Job Interface) 가지고 JobDetail build() 하는데, 스케쥴러는 그 job 실행 시 마다, 메서드 호출 전에 새 인스턴스를 만든다. 

When the execution is complete, references to the job class instance are dropped, and the instance is then garbage collected.

실행이 완료되면(작업 수행 끝), job 인스턴스가 참조한 객체가 죽고 garbage collector 가 수거해간다. (인스턴스 사망) 

One of the ramifications of this behavior is the fact that jobs must have a no-argument constructor (when using the default JobFactory implementation).

그 결과 , job 들은 반드시 default constructor 가져야함(when using the default JobFactory implementation)

Another ramification is that it does not make sense to have state data-fields defined on the job class - as their values would not be preserved between job executions.

또 상태값 관련 필드를 job 클래스가 가질 수 없다. 아까 말했듯이 매번 instance 가 사망하고 수거되고 새로 생기기 때문

You may now be wanting to ask “how can I provide properties/configuration for a Job instance?” and “how can I keep track of a job’s state between executions?” The answer to these questions are the same: the key is the JobDataMap, which is part of the JobDetail object.

그럼 job instance 에 대해서 프로퍼티나 설정은 어떻게 하는데? 

매 실행 사이의 job 상태는 어떻게 파악하는데?

대답은 하나: JobDataMap; JobDetail 객체의 part

(여기서 너무 행복했다. 아니 드디어 Javadoc 내부에서 봤던 JobDataMap 부분이 나와서 ㅠㅠ 이제 이해 가능~~)

 

JobDataMap

The JobDataMap can be used to hold any amount of (serializable) data objects which you wish to have made available to the job instance when it executes. JobDataMap is an implementation of the Java Map interface, and has some added convenience methods for storing and retrieving data of primitive types.

JobDataMap는 job instance 가 실행시에 사용할 serializable data object 를 갖고 있을 수 있다. (any amount of)

JobDataMap 은 Java Map 을 implements 한 것이고, primitive data getting and setting 시에 편리한 methods 갖고 있다.

 

job class 의 execute(..) body 에다 직접 datamap.get..(data) 를 해줘서 field 선언해줘도 되지만,

(method 이름은 get어쩌구 지만, 하는 역할은 일반적인 setter랑 비슷함)

job class 에 field 선언하고 setter 만들어주면, JobFactory 가 default constructor 로 job 을 생성하면서, dataMap 에 setter injection 해줘서, @Override 한 execute(..) body 가 clean 해진다.

(난 setter injection을 더 선호하는 편..)

 

Job State and Concurrency

설명에 앞서,  Quartz 가 말하는 방식, 용어 정리

In “Quartz speak”,

stored JobDetail as a “job definition” or “JobDetail instance”

executing job as a “job instance” or “instance of a job definition”

“job” as a named definition, or JobDetail

the class implementing the job interface as a “job class”

 

- 추가적인 class annotation 설정 관련 내용

Now, some additional notes about a job’s state data (aka JobDataMap) and concurrency. There are a couple annotations that can be added to your Job class that affect Quartz’s behavior with respect to these aspects.

@DisallowConcurrentExecution is an annotation that can be added to the Job class that tells Quartz not to execute multiple instances of a given job definition (that refers to the given job class) concurrently.
Notice the wording there, as it was chosen very carefully. In the example from the previous section, if “SalesReportJob” has this annotation, than only one instance of “SalesReportForJoe” can execute at a given time, but it can execute concurrently with an instance of “SalesReportForMike”. The constraint is based upon an instance definition (JobDetail), not on instances of the job class. However, it was decided (during the design of Quartz) to have the annotation carried on the class itself, because it does often make a difference to how the class is coded.

@PersistJobDataAfterExecution is an annotation that can be added to the Job class that tells Quartz to update the stored copy of the JobDetail’s JobDataMap after the execute() method completes successfully (without throwing an exception), such that the next execution of the same job (JobDetail) receives the updated values rather than the originally stored values. Like the @DisallowConcurrentExecution annotation, this applies to a job definition instance, not a job class instance, though it was decided to have the job class carry the attribute because it does often make a difference to how the class is coded (e.g. the ‘statefulness’ will need to be explicitly ‘understood’ by the code within the execute method).

If you use the @PersistJobDataAfterExecution annotation, you should strongly consider also using the @DisallowConcurrentExecution annotation, in order to avoid possible confusion (race conditions) of what data was left stored when two instances of the same job (JobDetail) executed concurrently.

해석 써놓기 힘들다.. 쉬운 영어니깐 걍 까먹으면 다시 읽어봐

 

 

JobExecutionException

Finally, we need to inform you of a few details of the Job.execute(..) method. The only type of exception (including RuntimeExceptions) that you are allowed to throw from the execute method is the JobExecutionException. Because of this, you should generally wrap the entire contents of the execute method with a ‘try-catch’ block. You should also spend some time looking at the documentation for the JobExecutionException, as your job can use it to provide the scheduler various directives as to how you want the exception to be handled. 

document 찾아봐.. job 이 스케쥴러한테 JobExecutionException 얼마나 다뤄질 지 지시하는 것을 위해서...

 

conclusion for Quartz
이틀하고 반나절 정도 지나고 나서, 드디어 lesson 3 까지 마쳤다. 
만약에 더 필요한 내용이 있다면, listener 정도만 보면 될 것 같다. 

 

'오늘의 배움' 카테고리의 다른 글

220826 오늘의 배움  (0) 2022.08.26
220824 오늘의 일기  (0) 2022.08.24
오늘의 배움을 시작하면서...  (0) 2022.08.24