Pages

레이블이 [ QUARTZ ]인 게시물을 표시합니다. 모든 게시물 표시
레이블이 [ QUARTZ ]인 게시물을 표시합니다. 모든 게시물 표시

2014년 2월 21일 금요일

[SPRING] Quartz를 이용한 JOB 스케쥴링 - (4)

Spring Quartz를 사용하기 위해서는 라이브러리가 필요하다.

현재 개발된 환경이 JAVA 1.5, TOMCAT 6.0 이다. 실제 사용한 라이브러리는

quartz-all-1.8.6.jar 을 사용하였다.

context 설정


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
   <!-- DAO Definition: iBatis implementations, sqlMapClient setter Injection -->
    <bean id="truncTableDao" class="com.batch.dao.TruncTableDaoImpl">
        <property name="sqlMapClient" ref="sqlMapClient"/>
    </bean>
 
    <!-- 간단한 절차 설명
        Step1. 반복할 작업을 가진 JobTask 클래스를 스케쥴러를 통해 실행하게 해주는 QuartzService 에 대한 Bean 정의
        Step2. JobDeailBean
        Step3. Quartz Trigger 정의
        Step4. SchedulerFactoryBean 에 설정한 JobDeailBean 과 Trigger 주입
     -->
    <!-- Step1. 주기적으로 실행될 JobTask 클래스 Bean 설정 -->
    <bean name="JobTask" class="com.batch.scheduler.JobTask">
        <property name="dao" ref="truncTableDao"></property>
    </bean>
    
    <!-- Step2. JobDeailBean 설정 -->
    <bean name="JobProcess" class="org.springframework.scheduling.quartz.JobDetailBean">
        <!-- jobClass: 실행시킬 클래스 -->
        <property name="jobClass" value="com.batch.service.QuartzService"></property>
        <property name="jobDataAsMap">
            <map>
                <!-- 실행시킬 클래스의 DI -->
                <entry key="jobTask">
                    <ref bean="JobTask"/>
                </entry>
            </map>
        </property>
    </bean>
    
    <!-- Step3. Trigger 설정
    Trigger의 종류
    1. CronTriggerBean: Linux의 CronTab과 동일
    2. SimpleTriggerBean: 보다 간단한 Trigger
     -->
    <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="jobDetail" ref="JobProcess"></property>
        
        <!-- 1시간 마다 반복 -->
        <property name="cronExpression" value="0 0 0/1 * * ?" />
        
        <!-- 15초 마다 반복 -->
        <!-- <property name="cronExpression" value="0/15 * * * * ?"/> -->
 
        <!-- value는 1000 이 1초 
         <property name="repeatInterval" value="10000"></property>
          -->
    </bean>
    
    <!-- Step4. SchedulerFactoryBean 에 설정한 JobDeailBean 과 Trigger 주입 -->
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="jobDetails">
            <list>
                <ref bean="JobProcess"/>
            </list>
        </property>
        <property name="triggers">
            <list>
                <ref bean="cronTrigger"/>
            </list>
        </property>
    </bean>


이제 모든 소스와 설정이 마무리 되었다. 서버를 실행해보면 다음과 나온다. 그럼 정상이며,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
14 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] INFO org.quartz.impl.StdSchedulerFactory - Using default implementation for ThreadExecutor
29 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] INFO org.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
29 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] INFO org.quartz.core.QuartzScheduler - Quartz Scheduler v.1.8.6 created.
30 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] INFO org.quartz.simpl.RAMJobStore - RAMJobStore initialized.
31 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] INFO org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v1.8.6) 'org.springframework.scheduling.quartz.SchedulerFactoryBean#0' with instanceId 'NON_CLUSTERED'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
 
31 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'org.springframework.scheduling.quartz.SchedulerFactoryBean#0' initialized from an externally provided properties instance.
31 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 1.8.6
33 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] INFO org.quartz.core.QuartzScheduler - JobFactory set to: org.springframework.scheduling.quartz.AdaptableJobFactory@7c2999bb
[02-21 17:31:41:583]<INFO > : Starting Quartz Scheduler now
34 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] INFO org.quartz.core.QuartzScheduler - Scheduler org.springframework.scheduling.quartz.SchedulerFactoryBean#0_$_NON_CLUSTERED started.


다음과 같이 설정해놓은 시간에 JOB이 실행되고 해당 테이블을 조회해보면 정상적으로 TRUNCATE 된 것을 확인 할 수 있다.


1
2
3
4
2014-02-21 17:00:00,020 DEBUG [java.sql.Connection.debug(27)] {conn-100072} Preparing Statement:    TRUNCATE TABLE SESSION  
2014-02-21 17:00:00,020 DEBUG [java.sql.PreparedStatement.debug(27)] {pstm-100073} Executing Statement:    TRUNCATE TABLE SESSION  
2014-02-21 17:00:00,021 DEBUG [java.sql.PreparedStatement.debug(27)] {pstm-100073} Parameters: []
2014-02-21 17:00:00,021 DEBUG [java.sql.PreparedStatement.debug(27)] {pstm-100073} Types: []

[SPRING] Quartz를 이용한 JOB 스케쥴링 - (3)

앞서 작성한 클래스를 수행하기 위한 JOB 클래스를 만들어보자.

패키지: com.batch.scheduler

1
2
3
4
5
6
7
8
9
10
11
public class JobTask {
    private TruncTableDao dao;
    public void setDao(TruncTableDao dao) {
        this.dao = dao;
    }
    
    public void truncateTableJob() throws DataAccessException, Exception {
        System.out.println("[ Job Task 실행 ] = " + new Date());
        dao.truncateTable();    // TRUNCATE TABLE
    } 
 }


패키지: com.batch.service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// QuartzJobBean 을 상속 받아야 한다.
public class QuartzService extends QuartzJobBean {
 
    private JobTask jobTask;
 
    public void setJobTask(JobTask jobTask) {
        this.jobTask = jobTask;
    }
 
    @Override
    protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {
        try {
            
            jobTask.truncateTableJob();    // TRUNCATE TABLE
            
        } catch (DataAccessException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


이제 JOB을 등록하기만 하면 된다.

[SPRING] Quartz를 이용한 JOB 스케쥴링 - (2)

다음 패키지에 두 파일을 생성한다. 실제 테이블을 TRUNCATE 하는 부분이다.

패키지: com.batch.dao



1
2
3
4
5
6
7
8
9
public interface TruncTableDao {
    /**
     * sample insert 
     * @return 
     * @throws DataAccessException
     * @throws Exception 
     */
    public void truncateTable() throws DataAccessException, Exception;
}




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
public class TruncTableDaoImpl extends SqlMapClientDaoSupport implements TruncTableDao {
    
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public void truncateTable()  throws DataAccessException, Exception {
        
        SqlMapClient smc = getSqlMapClient();
 
        int errCd = 0;
        String rstMsg = "";
        String modDt = "";            // 등록 날짜
        String modDt2 = "";
        String errDtl = "";
        
        JrConfigManager configMng = JrConfigManager.getInstance();
        String targetDir = configMng.getProperty("config.job.temp.dir");
        String fileName = configMng.getProperty("config.job.temp.file");;
        String targetFileName = targetDir + "/" + fileName; 
                
        File fileTmp = new File(targetDir);
 
        try{
            
            if(fileTmp.exists() == false){
                fileTmp.mkdirs();
                
                FileUtil.fileMake(targetFileName);
                
                System.out.println("FIRST - 1");
                BufferedWriter writer = new BufferedWriter(new FileWriter(targetFileName));
                writer.write("1");
                writer.close();
                
                smc.startTransaction();
                
                loggingCat.info("Query Call ID : JOB.truncateTable");
                smc.update("JOB.truncateTable");
                
                smc.commitTransaction();
            }else{
                File files = new File(targetFileName);
                
                if(files.exists() == false){
                    FileUtil.fileMake(targetFileName);
                }else{
                    FileReader fileReader = new FileReader(files);
                    BufferedReader reader = new BufferedReader(fileReader);
    
                    String number = null;
                    int cnt = 0;
                    
                    while((number = reader.readLine()) != null ){
                        cnt = Integer.parseInt(number);
                        
                        if(Integer.parseInt(number) == 1){
                            BufferedWriter writer = new BufferedWriter(new FileWriter(targetFileName));
                            writer.write("2");
                            writer.close();
                            
                            smc.startTransaction();
                            
                            loggingCat.info("Query Call ID : JOB.truncateTable");
                            smc.update("JOB.truncateTable");
                            
                            smc.commitTransaction();
                            
                        }else if(Integer.parseInt(number) == 2){
                            BufferedWriter writer = new BufferedWriter(new FileWriter(targetFileName));
                            writer.write("1");
                            writer.close();
                            
                            smc.startTransaction();
                            
                            loggingCat.info("Query Call ID : JOB.truncateTable2");
                            smc.update("JOB.truncateTable2");
                            
                            smc.commitTransaction();
                        }
                    }
                    reader.close();
                    
                    if(cnt == 0){
                        System.out.println("FIRST - 2");
                        BufferedWriter writer = new BufferedWriter(new FileWriter(targetFileName));
                        writer.write("1");
                        writer.close();
                        
                        smc.startTransaction();
                        
                        loggingCat.info("Query Call ID : JOB.truncateTable");
                        smc.update("JOB.truncateTable");
                        
                        smc.commitTransaction();
                    }
                }
 
            }
        }catch (Exception e){
            system.out.println(s.printStackTrace());
        }finally{
            smc.endTransaction();
        }
        
    }
}


config.job.temp.dir = c:/temp

config.job.temp.file = trunc

여기서 c:/temp/trunc 파일에 1과 2를 반복하면서 파일에 쓴다.

1일 때는 파일에 2를 쓰고 SESSION 테이블을 TRUNCATE 하겠다는 것이고,

2일 때는 파일에 1를 쓰고 SESSION2 테이블을 TRUNCATE 하겠다는 것이다.

다음 패키지를 생성하고 쿼리를 만들어 준다.

패키지: com.batch.sqlmap
파일명: JOB_oracle.xml


1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
 
<sqlMap namespace="JOB">
    <update id="truncateTable">
        TRUNCATE TABLE SESSION
    </update>
    
    <update id="truncateTable2">
        TRUNCATE TABLE SESSION2
    </update>
</sqlMap>