CronTrigger는 앞에서 살펴본 "cron 표현법"을 사용하여 스케줄링 기능을 제공한다.


작업(Job) 실행이 달력 개념을 기반으로 반복된다면  SimpleTrigger보다 CronTrigger가 더 유용하게 사용될 수 있다.


"매주 월요일부터 금요일까지 아침8시” 

"매달 마지막 금요일 새벽1시30분” 


하지만 cron 표현법 보다는 좀 더 자세한 설정이 가능한데 "초(seconds)" 와 "년(year)" 이다.

 필드

 필수

허용  

Special characters

 (seconds)

 Yes

 0-59

 , - * /

 (minutes)

 Yes

 0-59

 , - * / 

 (hours)

 Yes

 0-23

  , - * /

 날짜(day of month)

 Yes

 1-31

  , - * / ? L W

 (month)

 Yes

 1-12 or JAN-DEC

  , - * /

 요일(day of week)

 Yes

 1-7 or SUN-SAT

  , - * / ? L #

 (year)

 No

 empty, 1979-2099

  , - * /


다양한 특수문자 역시 동일하게 사용할수 있다.


* : 모든 값을 의미.

? : 특정 값을 정하지 않음.

- : 범위를 의미. 예) 0-10이면 0부터 10까지.

, : 값을 추가. 0-10,20-30은 0부터 10까지, 그리고 20부터 30까지.

/ : 증분을 의미. 예) 초에 0/15를 사용하면 15초마다(0, 15, 30, 45) .

L : 마지막을 의미. 날짜에 사용하면 월의 마지막 날을 의미. 

    31, 30 또는 28(윤달에는 29).

W : 주중(weekday)를 의미. 날짜와 같이 쓰면 그 날짜가 주중인 날을 의미. 


아래는 몇가지 예를 들어본것이다.



Expression

Meaning

0 0 12 * * ?

매일 12(정오)

0 15 10 ? * *

매일 오전 10 15

0 15 10 * * ?

매일 오전 10 15

0 15 10 * * ? *

매일 오전 10 15

0 15 10 * * ? 2005

2005년에 매일 아침 10 15

0 * 14 * * ?

매일 오후 2 0 ~ 59

0 0/5 14 * * ?

매일 오후 2시부터 2 55분까지 5분마다

0 0/5 14,18 * * ?

매일 오후 2시부터 2 55분까지 5분마다

6시부터 6 55분까지 5분마다

0 0-5 14 * * ?

매일 오후 2시부터 2 5분까지 매분

0 10,44 14 ? 3 WED

매년 3월의 수요일마다 오후 2 10분과 2 44

0 15 10 ? * MON-FRI

월요일부터 금요일까지 오전 10 15

0 15 10 15 * ?

매달 15 오전 10 15

0 15 10 L * ?

매달 마지막 오전 10 15

0 15 10 ? * 6L

매달 마지막 금요일 오전 10 15

0 15 10 ? * 6L 2002-2005

2002년부터 2005년까지 매달 마지막 금요일 오전 10 15

0 15 10 ? * 6#3

매달 3번째 금요일 오전 10 15

0 0 12 1/5 * ?

매달 첫날부터 5일마다 12(정오)

0 11 11 11 11 ?

매년 11 11 오전 11 11



output




소스 : https://github.com/redrebel/Scheduling

Posted by 빨강토끼
,

Quartz는 먼저 이전글(자바기반 스케줄링 프로그래밍(3) - java.util.java)의 맛집 예와 비교해보겠다.


지금 시간이 오후 2시이고 7시에 맛집에서 식사를 하려고 한다면,

1. 지금부터 5시간후에 가겠다고 맛집에 예약을 해놓는다.(음식도 주문한다)

2. 5시간후에 맛집에 가면 거의 기다리지 않고 바로 먹을 수 있다.


Quartz 의 공식 사이트와 다운로드 할 수 있는 주소는 아래와 같다.

http://www.quartz-scheduler.org/

http://www.quartz-scheduler.org/downloads


모듈 : 설명

quartz-2.2.1.jar : Quartz 코어 

quartz-jobs-2.2.1.jar : Quartz Job 지원



Maven

<dependency> 

  <groupId>org.quartz-scheduler</groupId>

  <artifactId>quartz</artifactId> 

  <version>2.2.1</version> 

</dependency> 

<dependency> 

  <groupId>org.quartz-scheduler</groupId> 

  <artifactId>quartz-jobs</artifactId> 

  <version>2.2.1</version> 

</dependency>


quartz를 사용하기 위해서는 몇가지 알아야되는 것들이 있는데,

그중 Trigger 라는 것이 있다.


이론적인 설명은 구글링을 통하여 각자 알아보길 바란다.


우선 이번 글에서는 Trigger 중 SimpleTrigger 를 설명하고 

CronTrigger 에 대한것은 다음글에 설명하도록 하겠다.


SimpleTrigger : 사용이 간단하며 interval, delay, repeat times등을 설정 할 수 있다.



output



거의 일정한 시간간격으로 실행된다.

Posted by 빨강토끼
,

public void java.util.Timer.schedule(TimerTask task, Date firstTime, long period)

Parameters: 

task - 스케줄링 되어 실행될 task. 

firstTime - 실행될  task의 처음시각. 

period - task가 실행될 주기(millisecond). 




output


java.util.Timer 는 단점이 있다.

output 을 보면 0.001~0.002초씩 로그시간이 지연이 발생되는것을 알수있다.


자바의 특성과 다양한 플랫폼에서의 구현때문에, 각각의 JVM에서의 Thread 스케줄링의 구현은 일치하지 않는다.

Task는 Runnable 객체로 구현되어 있고 일정시간동안 sleep상태가 된다. 그러면 Timer가 규정된 순간에 task를 깨운다. 그러나 정확한 실행시간은 JVM 의 스케줄링 정책과 현재 얼마나 많은 Thread가 프로세서를 기다리고 있냐에 따라 달라진다.

Task가 지연되는 경우는 크게 2가지이다.

- 많은 수의 쓰레드가 실행되기를 기다리고 있는 경우

- GC 에 의한 지연

각 Timer 객체는 쓰레드를 백그라운드로 시작한다.

이러한 방식은 J2EE 애플리케이션 서버와 같은 환경에서는 바람직하지 않을 것이다.

왜냐하면 이러한 쓰레드들이 컨테이너 영역 내에 있지 않기 때문이다.



예를 들어 

지금 시간이 오후 2시이고 7시에 맛집에서 식사하려고 한다면,

1.지금부터 5시간후에 맛집에가서 식사를 하겠다고 계획을 세운다.

2.5시간후에 맛집에 도착한다.

3.하지만. 이미 손님들이 줄을 서있어서 기다려서 먹어야한다….


이해하기 쉽게 하기 위하여 예를 든것이므로 혹시 잘못 이해하지 않길 바란다.

그럼 나름 정확한 시간간격으로 실행되거나 특정한 날이나 요일등의 달력기반의 스케줄링을 하려면 
어떻게 해야할까?

다음에 설명할 Quartz를 사용하면 된다.


Posted by 빨강토끼
,

cron 은 오랬동안 사용되어오며 스케줄링 성능의 입증되어온 유닉스의 툴이다.


cron 명령어는 OS마다 다소의 차이가 있지만 리눅스 기준으로


$crontab -e [엔터]


1 2 3 4 5  사용자아이디 명령어

 

1: minute (0-59)

2: hour (0-23)

3: day of the month(1-31)

4: month of the year(1-12) OR jan, feb, mar, apr ...
5: day of the week (0-6)(Sunday=0 or 7) OR sun, mon, tue, wed, thu, fri, sat


순으로 입력하고, 명령어란에 여러분이 만든 어플이나 실행스크립트를 넣어서 사용한다.


예를 들어 아래와 같은 명령이 있다고 하면

#date time sync

0 5 * * * root /usr/bin/rdate -s time.bora.net && /sbin/hwclock -w



매일 , 오전 5시 0분에 시스템의 기준시를 맞추는 동작(/usr/bin/rdate -s time.bora.net && /sbin/hwclock -w)을 하게 된다.


다른 예로는 OS X 에서 아래와 같은 명령은 매1분마다 date.txt 라는 파일에 현재시간을 기록하는 cron 명령이다. 

0/1 * * * * date >> /Users/red/date.txt



0/1 같이 다양한 특수문자를 사용할수 있다.


* : 모든 값을 의미.

? : 특정 값을 정하지 않음.

- : 범위를 의미. 예) 0-10이면 0부터 10까지.

, : 값을 추가. 0-10,20-30은 0부터 10까지, 그리고 20부터 30까지.

/ : 증분을 의미. 예) 초에 0/15를 사용하면 15초마다(0, 15, 30, 45) .

L : 마지막을 의미. 날짜에 사용하면 월의 마지막 날을 의미. 

    31, 30 또는 28(윤달에는 29).

W : 주중(weekday)를 의미. 날짜와 같이 쓰면 그 날짜가 주중인 날을 의미. 


로그 파일 백업이나 주기적으로 간단한 동작을 하는  명령이나 프로세스에 적당하다.



Posted by 빨강토끼
,

어떤 프로젝트에서 , 특정 시각이나 일정시간 간격으로 job 실행되어야 하는 경우가 있다.


매일 혹은 매월 통계데이터를 만들어야 되는 배치성 업무나, 일정 주기별로 서비스의 상태나 변경사항을 관리자에게 알려줘야되는 업무가 예다.



일반적으로 Java Timer API  crontab, Quartz 구현한다.

( 외에도 다수의 job scheduler library 존재한다.)


나는 PG(Payment Gateway) 개발을 하고 있다.


나의 경우에는 아래와 같은 배치성 업무들이 있다


  • 매일 새벽에 그전날 결제건에 대한 통계생성

  • 외부 PG업체에서 전날의 결제정보를 받아와 우리시스템과의 대사작업 수행

  • 매월 초 이전달 결제에 대한 정산작업

  • 매월 말 이전달 결제에 대한 청구작업 

각 업무의 특성에 맞게 crontab 과 quartz 를 선택하여 사용하고 있다.


자바기반 스케줄링 프로그래밍에 대한 자세한 내용은 아래 페이지를 참조하면 된다.


참조 :

http://archive.oreilly.com/pub/a/java/archive/quartz.html

http://tmwalker.tistory.com/36 (번역)

Posted by 빨강토끼
,

Secure Coding

프로그래밍/JAVA 2014. 9. 17. 14:58

보안에 문제가 되는 코딩 취약점(43)


1. 입력 데이터 검증 및 표현(14)

 SQL 인젝션

자원삽입

크로스 사이트 스크립트

운영체제 명령어 삽입

위험한 형식 파일 업로드

신뢰되지 않는 URL 주소로 자동접속연결

XQUERY  삽입

XPATH 삽입

LDAP 삽입

크로스 사이트 요청 위조

디렉토리 경로 조작

HTTP 응답분할

정수 오버플로우

보호메커니즘을 우회살 수 있는 입력 값 변조


2. 보안기능(16)

적절한 인증 없는 즁요기능 허용

부적절한 인가

중요 자원에 대한 잘못된 권한 설정

취약한 암호화 알고리즘 사용

사용자 중요정보 평문 저장 및 전송

하드코딩된 패스워드

충분하지 않은 키 사용

적절하지 않은 난수 값

패스워드 평문저장

취약한 패스워드 허용

사용자 하드디시크에 저장되는 쿠키를 통한 정보노출

보안속성 미적용으로 인한 쿠키노출

주석문에 포함된 패스워드 등 개인정보

소트없이 일방향 해쉬함수 사용

무결성 검사없는 코드 다운로드


3. 시간 및 상태(2)

검사시점과 사용시점

제어문을 사용하지 않는 재귀함수


4. 에러처리(3)

오류메시지를 통한 정보 노출

오류 상황 대응 부재

적절하지 않은 예외 처리


5. 코드 오류

NULL 포인트 역참조

부적절한 자원 해제

 

Posted by 빨강토끼
,

현재 Quartz 는 버젼이 2.2.1 까지 릴리즈됐음 (2013년 9월 24일)


JDK 1.6에서 빌드되어서 배포중 이다.


JAVA 1.5 에서 시스템을 운영중이라면 Quartz 1.7.3 이전버젼을 사용해야된다.

http://quartz-scheduler.org/downloads



Posted by 빨강토끼
,

LOG4J의 차세대 버전인(사실 공개된지 오래됨) LOGBACK을 GITHUB를 통해 다운받았습니다.


이유는 logback의 주요기능중에  설정파일의 Dynamic Reloading 지원 이라는 것이 있는데

매번 전체 설정정보를 reload 하는지 아니면 변경여부(사이즈 등)을 확인후 변경된 것 같으면

reload를 하는지 궁금해서였습니다.


git clone https://github.com/qos-ch/logback.git


소스를 다운받았으니 빌드(이클립스)를 해보고 싶었습니다.

http://logback.qos.ch/setup.html#ide


IntelliJ 에서는 손쉽게 프로젝트를 import해서 사용해볼수 있는데

이클립스에서는 조금 어렵더군요...


사이트에 있는 데로 번역을 해봤습니다.

1. 이클립스를 설치합니다.

2. Groovy 플러그인을 설치합니다.

    . 자신의 이클립스버전에 맞는 플러그인을 사용해야합니다.확인

    예를 들어 이클립스 4.2(Juno)라면 update site 는 http://dist.springsource.org/release/GRECLIPSE/e4.2/ 입니다.

    . 이클립스에서 "help->install new Software->Work with" 에서 상기 update site 를 입력합니다.

    . Groovy-Eclipse Feature" 를 선택합니다. "m2e Configurator for Groovy-Eclipse"는 필요하지 않습니다.

3. $LOGBACK_HOSE(LOGBACK의 소스를 GITHUB로 다운받은 디렉토리)로 이동합니다.

4. 만약에 .settings, .classpath, .project 파일이 폴더에 있다면 삭제합니다(하위폴더 포함)

5. 명령창에서 mvn eclipse:eclipse 라고 명령을 입력합니다. 여기서 문제가 있었는데 별도로 정리하겠습니다.

6. 이클립스에서 LOGBACK 프로젝트를 import합니다. Import->General->Existing projects 에서 $LOGBACK_HOSE 를 선택합니다.

7. 이클립스에서 logback-classic/target/generated-sources/groovy-stubs/main 디렉토리를 소스폴더에서 제거합니다.

    (logback-classic->project properties->Java Build Path)

8. 이클립스에서 모든 프로젝트를 Clean 합니다.(Project->Clean)

9. 이클립스에서 logback-classic 프로젝트를 선택하고 Groovy project 로 변환합니다.

   (logback-classic 프로젝트에서 Configure->Convert Groovy to Project)



Posted by 빨강토끼
,

불과 저번주까지 log4j만 쓰다가 slf4j를 통해 logback 을 사용해보기로 결정했습니다.

사실 logback이라는게 있다는걸 오늘 알았습니다. ㅡㅡ;

다들 아는 사실이겠지만 log4j를 만든사람이 새롭게 만든 log관련 라이브러리라서 (이유)

log4j를 사용해본 분들이라면 손쉽게 적응할수 있다고 합니다.



http://logback.qos.ch/



간단하게 본인위주로 정리하겠습니다.

자세한 설명은 맨아래 참조란을 따라가시면 됩니다.



1. 새롭게 제공되는 주요 기능 및 개선

 . log4j에 비해 속도나 메모리 사용면에서 개선

 . 설정파일의 Dynamic Reloading 지원

 . 설정파일의 조건부 처리 기능

 . 로그파일에 대한 자동압축, 자동 삭제 기능 제공

 . 런타임에 설정한 값에 따라 로그를 분리하여 처리할 수 있는 SiftingAppender 제공

 . groovy 언어로 설정파일 작성 기능

 . FileAppender 사용 시 다수의 JVM이 동시에 하나의 파일에 로그를 남길 수 있는 prudent mode를 지원

 . 다양한 조건에 따른 로깅처리 여부를 결정할 수 있는 Filter 제공


이것중에 관심이 가는 것은 설정파일의 Dynamic Reloading 지원 , 로그파일에 대한 자동 압축, 자동 삭제기능 제공 입니다.


2. Dynamic Reloading 지원

예전같으면 INFO 모드로 로그를 쌓고 있다가 여러가지이유로 DEBUG모드로 로그를 쌓고 싶을때 

설정화일을 변경하고 서버를 재기동해야 했습니다.

하지만 LOGBACK에서는 설정을 바꾸면 주기적으로 변경사항이 있는지 체크하여 자동으로 설정파일의

내용을 reloading 하여 변경합니다.


방법은

<configuration scan="true" scanPeriod="30 seconds"> ..... </configuration>


이렇게하시면 됩니다.


그럼 30초단위로 설정화일을 스캔합니다.


3. 로그파일에 대한 자동압축, 자동 삭제기능 제공

저역시 하루에 몇기가씩 로그가 쌓이는(INFO인데도...) 서버를 운영중입니다.

그래서 그전에 했던 방법은 주기적으로 하루전의 로그파일을 압축해서 보관하는 스크립트를 작성하여

crontab으로 스케줄링하여 사용하고 있었습니다.

하지만 logback에서는 스스로 이러한 처리를 할수있는 옵션을 제공합니다.


 <configuration scan="true" scanPeriod="30 seconds">
        .....
 </configuration>
 
 <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 
            
            <fileNamePattern> someFileName.log.zip (or gz) </fileNamePattern>

              <maxHistory>90</maxHistory>     
        </rollingPolicy> 
        ....
    </appender>


fileNamePattern : 마지막 확장자를 zip 이나 gz 로 지정하면 자동으로 압축합니다.

maxHistory : (조금 혼란스러웠지만 이제는 이해가 되는 내용이였습니다). 남겨놓을 로그파일의 갯수입니다.

즉 size 단위로 한다고 하면 90개가 넘어가게 되면 옛날것부터 삭제합니다.

그리고 백업을 SIZE 단위가 아니고 매일단위로 백업을 한다면 위에같은 경우에는 

90일동안 보관하다가 삭제를 하게됩니다.

(정확히 말하자면 90개가 넘어가게되면 옛날것부터 삭제).

그리고 만일 매월단위로 백업을 한다면 90개월후에 삭제되겠지요.

이해가 되시나요? 그럼 만일 중간의 파일을 임의로 삭제하게된다면?

저도 테스트해보고 블로그에 남기도록 하겠습니다.


참조

http://dev.anyframejava.org/docs/anyframe/plugin/optional/logback/1.0.2/reference/html/index.html

logback 사용해야 하는 이유 (Reasons to prefer logback over log4j)

Posted by 빨강토끼
,

특정월의 메인아이디 별로 매출을 뽑을려고 다음과 같이 코딩을 하였습니다.

sql.xml 소스

<mapper namespace="billMapper">

 <select id="selectListByMonth" parameterType="String" resultType="List<net.red.vo.ResVo>">

 SELECT B.MID, SUM(A.AMT_VAT)/1.1 AS AMT , SUM(A.AMT_VAT) AS TOT_AMT

 FROM UTH A

  WHERE DT LIKE #{value} || '%'

    GROUP BY B.MID 

 </select>

</mapper>


a.java 소스

List<ResVo> listResVo = (List<ResVo>)session.selectList("mapper.selectListByMonth", yyyymm);


MyBatis 에 대하여 경험이 적는 저로서는 문제가 없어보이는 코드였다...

그런데 에러가 났습니다. 컴파일부터 안됐습니다....


구글을 뒤져봐도 한글로 된 제대로된 설명이 없었습니다. ㅜㅜ

심지에 MyBatis 공식 메뉴얼에도 설명을 잘 못찾겠었습니다.


안되는 영어를 보면서 알고 봤더니. 이유가 있었습니다.


너무 쉬운 계념이라서 그랬습니다. ㅡㅡ;


아래는 정상적으로 동작하는 소스입니다.


sql.xml 소스

<mapper namespace="billMapper">

 <select id="selectListByMonth" parameterType="String" resultType="net.red.vo.ResVo">

 SELECT B.MID, SUM(A.AMT_VAT)/1.1 AS AMT , SUM(A.AMT_VAT) AS TOT_AMT

 FROM UTH A

  WHERE DT LIKE #{value} || '%'

    GROUP BY B.MID 

 </select>

</mapper>


a.java 소스

List<ResVo> listResVo = session.selectList("mapper.selectListByMonth", yyyymm);


즉...구지  resultType="List<net.red.vo.ResVo>" 라고 해서 정의하지 않아도

selectList 를 사용하면 <select> 에서는 net.red.vo.ResVo 라는 List 

(즉 여러개의 ResVo 들...)로 회신을 해주는 개념이였습니다.



Posted by 빨강토끼
,