Spring의 @Scheduled annotation으로 설정된 cron expression을 테스트하기 by 정상혁

 

 Spring 3.0부터는 Quartz가 없이도 실행 스케쥴 설정이 가능합니다. 설정과 테스트 방법을 정리했습니다.

 

@Schedule 를 써서 크론 표현식 설정

  실행을 하고 싶은 메소드를 @Component, @Schedule annotaion을 통해 지정을 합니다.


@Component
public class BaseballScheduledJobLauncher extends JobLaunchSupport {

.....

    @Scheduled(cron="45 * * * * MON-FRI")
    public void baseballJob() {
        JobParameters params = createTimeParameter();
        run("baseballJob", params);
    }

   
    @Scheduled(cron="45 10 5 * * MON-FRI")
    public void baseballExportJob() {
        JobParameters params = createTimeParameter();
        run("baseballExportJob", params);
    }

}


 java 파일에 설정된 Annotation을 인식하기 위해서 Application context의 xml파일에 component-scan과 annotation으로 schedule을 설정하겠다는 선언을 추가합니다.  그리고 schedule을 실행할 thread pool의 크기도 지정합니다.


    <context:component-scan base-package="edu.batch.baseball.schedule"/>
    <task:scheduler id="myScheduler" pool-size="10"/>
    <task:annotation-driven scheduler="myScheduler"/>


 'task'와 'component'의 namespace가 xml에 추가되어 있어야 합니다.

테스트 코드

 테스트 코드를 단순하게 만들기 위해서 크론표현식을 추출하고 검사하는 코드는 SpringCronE-pressionTestUtils클래스로 분리했습니다.

 

package edu.batch.baseball.schedule;

import static edu.batch.support.launch.SpringCronE-pressionTestUtils.*;

import java.util.Arrays;
import java.util.List;

import org.junit.Test;

import edu.batch.baseball.schedule.BaseballScheduledJobLauncher;

public class BaseballScheduledJobLauncherTest {

    private static final String DATE_PATTERN = "yyyy/MM/dd hh:mm:ss";

    @Test
    public void testBaseballJobSchedule() {
        String initialTime = "2010/09/01 09:00:00";
        List<String> expectedTimeList = Arrays.asList(
                "2010/09/01 09:00:45",
                "2010/09/01 09:01:45",
                "2010/09/01 09:02:45");
        String cronE-pression = getCronE-pressionOfMethod(BaseballScheduledJobLauncher.class, "baseballJob");
        assertSchedule(cronE-pression, initialTime, expectedTimeList,DATE_PATTERN);
    }
}


 

 SpringCronE-pressionTestUtils

첨부파일 : SpringCronE-pressionTestUtils.java

 

package edu.batch.support.launch;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import java.lang.reflect.Method;
import java.text.ParseException;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.scheduling.support.SimpleTriggerContext;

public class SpringCronE-pressionTestUtils {

 public static String getCronE-pressionOfMethod(Class<?> targetClass,
   String methodName)  {
  Method scheduledMethod;
  try {
   scheduledMethod = targetClass.getDeclaredMethod(methodName,
     new Class[] {});
  } catch (SecurityException e) {
   throw new IllegalArgumentException("cannot access the method : " + methodName, e);
  } catch (NoSuchMethodException e) {
   throw new IllegalArgumentException(e);
  }
  Scheduled scheduleInfo = scheduledMethod.getAnnotation(Scheduled.class);
  String cronE-pression = scheduleInfo.cron();
  return cronE-pression;
 }

 

public static void assertSchedule(String cronE-pression, String initialTime,
   List<String> expectedTimeList, String datePattern) {
  CronTrigger trigger = new CronTrigger(cronE-pression);
  Date startTime;
  try {
   startTime = DateUtils.parseDate(initialTime,
     new String[] { datePattern });
  } catch (ParseException e) {
   throw new IllegalArgumentException("wrong date format", e);
  }
  SimpleTriggerContext context = new SimpleTriggerContext();
  context.update(startTime, startTime, startTime);

  for (String exptectedTime : expectedTimeList) {
   Date nextExecutionTime = trigger.nextExecutionTime(context);
   String actualTime = DateFormatUtils.format(nextExecutionTime,
     datePattern);
   assertThat("executed on expected time", actualTime,
     is(exptectedTime));
   context.update(nextExecutionTime, nextExecutionTime,
     nextExecutionTime);
  }
 }

}

 


덧글

  • 리오 2012/05/14 20:54 # 삭제 답글

    질문이 하나 있는데요. CronExpression을 DB에서 불러와서 배치시간을 변경해 주는게 가능할까요??
  • 정상혁 2012/05/17 10:51 #

    보통 그럴 때는 1분에 한번씩 배치를 돌려서 현재 시간과 일치하는 Cron expressiond이 있는지 확인해서 해당하는 Job을 실행하는 방식을 쓴 프로젝트를 몇군데 본적이 있습니다.
    그외 처음에 어플리케이션이 올라갈때 DB에서 스케쥴 정보를 읽어오는 경우도 있었습니다.

    스케쥴링 정보가 DB에 있고, 어플리케이션 실행 중간에 스케쥴링 주기를 바꿀 수 있다면, 그 정보를 DB에서 읽을 주기를 적당히 정해야 겠죠.
  • viagra 2017/02/01 16:31 # 삭제 답글

    Womenra Usage The tablets of http://v1onlinepharm.com/ , for women are taken inside orally.
  • cialis 2017/02/28 15:07 # 삭제 답글

    Here 's one nose for you, take long now and get /http://cia1sideffects.com/ , -va-bene-per-le-donne/ .
  • James 2017/04/21 04:10 # 삭제 답글

    It is appropriate time to make some plans for the future and it is time to be happy. I have read this post and if I could I want to suggest you few interesting things or suggestions. Maybe you can write next articles referring to this article. I wish to read more things about it!
  • James 2017/05/12 20:58 # 삭제 답글

    You are my inspiration , I have few web logs and very sporadically run out from to brand.
  • James 2017/08/09 22:43 # 삭제 답글

    Enjoyed studying this, very good stuff, regards . A man may learn wisdom even from a foe. by Aristophanes.
  • James 2017/11/04 01:13 # 삭제 답글

    Hi there! I could have sworn I've been to this blog before but after checking through some of the post I realized it's new to me. Nonetheless, I'm definitely happy I found it and I'll be bookmarking and checking back frequently!
댓글 입력 영역