'Spring Batch'에 해당되는 글 26건

  1. 2010/01/28 [Spring Batch] Spring Batch Monitoring System by 자바지기
  2. 2009/04/14 [Spring batch]차세대 배치시스템 구축 성공전략 - JCO컨퍼런스 (2)
  3. 2009/02/02 [Spring batch]배치 어플리케이션 실행 스크립트와 빌드 (2)
  4. 2009/01/19 스프링배치 국내 자료 모음
  5. 2009/01/12 [Spring batch] 스프링배치 연재(16) DB to XML 파일 만들기 예제
  6. 2008/12/30 올해의 스프링 기술 top5, 내년 유망 스프링 기술 top5 (안영회 편) (4)
  7. 2008/12/30 [Spring batch] 스프링배치 연재(15) 하이버네이트 활용과 여러파일 읽기
  8. 2008/12/29 올해의 스프링 기술 top5, 내년 유망 스프링 기술 top5 (benelog 편)
  9. 2008/12/27 [Spring batch] 스프링배치 연재(14) 드라이빙 쿼리와 iBatis의 활용
  10. 2008/12/16 [Spring batch] 스프링배치 연재(13) 스프링배치의 형제들
2010/01/28 20:34

[Spring Batch] Spring Batch Monitoring System by 자바지기



  자바지기 박재성님께서 Spring Batch의 메타데이터 테이블을 조회하고 Job을 수동실행 시킬 수 있는 관리프로그램을 개발하셨습니다. 즉, 배치작업들의 실행결과, 실행시각, 처리한 건수 등을 조회하고, 필요하다면 웹브라우저를 통해 Job을 실행할 수도 있는 것이죠.

Spring Batch Monitoring System 공개 및 요구사항 수렴 
Spring Batch Monitoring System 개발자 인터뷰

  앞으로 많은 분들에게 도움이 될 수 있는 프로젝트로 발전이 될 것이라 믿습니다.


Trackback 0 Comment 0
2009/04/14 08:54

[Spring batch]차세대 배치시스템 구축 성공전략 - JCO컨퍼런스

2009.04.30  수정이력 :
 해당 프로젝트 사이트에 대해서 잘 못 전달될 수 있는 내용이 글에 포함되어서, 해당 부분은 삭제했습니다. 해당 사이트의 극히 일부 개발자의 단순한 언급, 그것도 농담일 수도 있는 내용이 다수의 반응처럼 오해될 수 있는 부분이 있었고, 공식 발표 내용에는 포함되지 않은 내용도 있어서 본의아니게 발표자나 관련 사업자분들께 누를 끼쳐드린 것 같습니다. 비록 익명으로 된 해당사례가 올라와 있지만, 제가 보다 신중을 기하지 못하여 마음을 상하신 분들이 있다면  사과드립니다. 그리고 글 후반후에 제가 다른 발표에서 받은 질문과 일반적인 내용에 대해서 덧붙여서 언급한 내용이 있는데, 해당 사이트 사례와 전혀 관계가 없지만, 글을 빨리 읽으시는 분들께는 연결해서 생각할 수 있는 오해의 여지가 있을 것 같아서 그 부분도 삭제했습니다.  이 포스트에 포함된 내용으로 사실과 다르게 사례가 전달된다면 전적으로 제 잘못입니다.
  이 포스트를 포함하여 글의 내용에 대한 문의와 정정요청은 benelog[at]gmail[dot]com으로 해주시면 업무시간 외의 시간에는 최대한 빨리 답변드리겠습니다.  



  물개선생님 김승권님이 2009년 JCO 컨퍼런스에서 발표하신, 국내 대형 보험사에 Spring batch 기반으로 배치프레임웍을 적용한 사례입니다. 해당 보험사는 처리 자료 건수가 1억건 단위에 운영인력 50명, 800여건 작업을 돌리는 큰 규모의 배치 시스템을 가지고 있다고 합니다. 

   그 프로젝트에서는 개발자들이 더 쉽게 프레임웍을 적용하기 위해서 Job의 유형별로 설정을 간편하게 만들 수 있는 FactoryBean을 제공했다고 합니다.   그렇게 Job유형별로 설정이 정리되니, Spring의 설정파일을 읽어서 배치Job에 대한 정리된 정보와 통계까지 볼 수 있는 관리화면도 제공할 수 있게되는, 처음에는 생각하지 않았던 장점도 생겼다고 하네요. 저도 프로젝트에서는 같은 유형의 Job의 설정에는 중복코드가 없게 하기 위해서 유형에 따른 FactoryBean을 만들고 bean 설정에서 parent 속성을 이용했었는데, 그런 시도는 스프링배치를 실무에 적용할 때 프로젝트의 특수성을 반영하면서도 간편한 코드를 만들기 위한 필수적인 절차라고 생각되었었습니다.

  그리고, 중간의 Wrapping 계층을 두어서 최종 개발자들의 요구사항을 반영할 수 있는 확장점을 만들고, Spring batch의 API변화에 대처할 수 있도록 했다고 합니다. 재미있게도, 이 구조가 ItemProcessor 등 Spring batch 2.0구조와 상당히 비슷해서 프로젝트 내부의 정보가 스프링 쪽에 세어나간  것이 아닌가 하는 농담도 나왔었다고 합니다. [각주:1]

http://static.springsource.org/spring-batch/migration/2.0-highlights.html

http://forum.ksug.org/viewtopic.php?f=6&t=468

Spring Batch 1.0에서 2.0으로 진화하기- 1. ItemReader/ItemWriter(1)

Spring Batch 1.0에서 2.0으로 진화하기- 1. ItemReader/ItemWriter(2)

Spring Batch 1.0에서 2.0으로 진화하기- 3. JobExecutionLisneter & 4. ItemProcessor

Spring Batch 1.0에서 2.0으로 진화하기- 5. Configuration

'>

  그 외에도 기술 지원을 위한 프레임웍 운영팀의 역할이 커졌던 점과 프레임웍 적응을 위한 학습기간이 필요했던 점,  개발계보다 훨씬 많은 건 수의 데이터가  Skip이 일어날 수 있는 운영계의 데이터 특성이 개발계에서 모두 반영되지 못해서 나중에 대처를 했었던 사례 등을 들을 수 있었습니다.

- 정상혁  (http://benelog.egloos.com)


Trackback 0 Comment 2
2009/02/02 08:09

[Spring batch]배치 어플리케이션 실행 스크립트와 빌드

  스프링배치를 처음 접할 때는 만들어진 Job을 어떻게 빌드하고, 실행시킬지가 감이 잘 잡히지 않을 수도 있습니다. Qurtz를 이용한 스케쥴링을 하고 Web Application Server안에서 실행시킨다면 다른 Web application과 같이 배포시킬 수도 있을 것입니다. 그래도  스프링배치 연재(10) JobLauncher와 Job, Step에 서 소개한 것처럼 CommandLineJobRunner 를 사용하여 직접 console에서 실행시키는 것이 가장 기본적인 실행법이라고 생각됩니다. 그리고 스케쥴링도 하루에 4~5번 정도 실행되는 정도의 작업이라면, 초기 클래스 로딩시간에 대한 큰 부담이 없으므로 Cron을 배치잡을 실행하는 스크립트를 호출하는 것이  더 간편하기도 합니다. 이처럼 command line에서 바로 배치잡을 실행시킬 때, Job이 참조하는 jar파일들을 같이 묶고, 실행할 때 그 jar들을 classpath에 지정하는 스크립트를 만드는 과정을 정리해 봅니다.

   먼저 배치Job을 실행시킬 수 있는 스크립트를 만들어 봅니다. -classpath 지정을 특정 디렉토리 아래에 있는 *.jar파일을 다 포함시키도록 만드는 것이 편리합니다. Tomcat 같은 java application을 실행시키는 쉘스크립트를 보면, 이런 부분이 다 유사하게 들어가 있습니다.

   다음은 Windows 계열에서 실행시킬 수 있는 runJob.bat파일의 예제입니다. JAVA_HOME 환경변수에 실행하고자 하는 JAVA버전이 있는 디렉토리가 지정되어 있어야 합니다. 스크립트가 있는 곳 아래 /lib 폴더 아래에 job에서 참조하는 jar파일이 있는 것으로 설정했습니다.

@echo off
set JAVA_CMD=%JAVA_HOME%\bin\java
set MAIN_CLASS=org.springframework.batch.core.launch.support.CommandLineJobRunner
set CLASSPATH=.
FOR %%F IN (*.jar) DO call :addcp %%F

FOR %%F IN (lib\*.jar) DO call :addcp %%F
goto extlibe

:addcp
set CLASSPATH=%CLASSPATH%;%1
goto :eof

:extlibe

"%JAVA_CMD%" -Xmx512M -cp "%CLASSPATH%" %MAIN_CLASS% %*

  이 파일을 이용해서 특정 Job을 실행시키는 스크립트를 따로 만들 수 있습니다.


cd /D D:\workspace\imaso-batch\deploy
runJob.bat applicationContext.xml teamDbToXmlJob %*

   CommandLineJobRunner의 형식과 마찬가지로 runJob.bat [설정파일명] [Job의 bean id] [파라미터1] [파라미터2]... 의 형식입니다. 설정파일에는 해당하는 Job에 대한 설정과 공통적인 JobLauncher, Database에 대한 설정 등 Job에서 필요한 모든 설정이 다 포함되어야 합니다. 공통적인 부분과 특정 Job에만 필요한 것을 잘 분리해서 include 등을 이용해서 applicationContext 파일을 구성하는 것이 여러 Job을 관리할 때 효율적인 것입니다.


  다음은 리룩스나 유닉스에서 실행되는 runJob.sh 쉘스크립트의 예제입니다. run.bat와 마찬가지로 실행위치/lib에 참조하는 라이브러리의 jar파일이 했지만, imaso-batch.jar라는 파일하나는 실행위치 디렉토리에 있는 것을 따로 지정하도록 했습니다.

#!/bin/sh
BASEDIR=`dirname $0`
cd $BASEDIR

CLASSPATH=$BASEDIR
CLASSPATH=$CLASSPATH:$BASEDIR/imaso-batch.jar

for f in `find $BASEDIR/lib -type f -name "*.jar"`
do
   CLASSPATH=$CLASSPATH:$f
done

JAVA_BIN=$JAVA_HOME/bin/java
OPT="-cp $CLASSPATH -Xmx512M"

echo $JAVA_BIN
$JAVA_BIN $OPT org.springframework.batch.core.launch.support.CommandLineJobRunner


  runJob.sh를 이용해서 특정 Job을 실행시키는 스크립트를 다음과 같이 만듭니다.

#!/bin/sh
BASEDIR=`dirname $0`
cd $BASEDIR
sh runJob.sh applicationContext.xml teamDbToXmlJob "${1+$@}"

  이제 이런 스크립트와 jar파일들을 같이 배포할 수 있도록 Maven에 설정을 추가합니다.

  pom.xml에 배포시 필요한 jar파일들을 같이 복사할 수 있도록 <build/>절 밑에 다음과 같이 maven-dependency-plugin의 설정을 추가합니다. 예제에서는 ${basedir}/deploy/lib 폴더로 복사되게 했습니다.


<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <version>2.0</version>
  <executions>
    <execution>
      <id>copy-dependencies</id>
      <phase>package</phase>
      <goals>
        <goal>copy-dependencies</goal>
      </goals>
      <configuration>
        <outputDirectory>${basedir}/deploy/lib</outputDirectory>
        <overWriteReleases>false</overWriteReleases>
        <overWriteSnapshots>false</overWriteSnapshots>
        <overWriteIfNewer>true</overWriteIfNewer>
      </configuration>
    </execution>
 </executions>

</plugin>


   그리고 Job의 구성을 위해 작성한 xml파일과 class파일들을 jar로 묶을 수 있도록 jar plugin을 설정합니다. ${basedir}/deploy로 복사하도록 했습니다.

<plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-jar-plugin</artifactId>
   <configuration>
     <outputDirectory>${basedir}/deploy</outputDirectory>
    </configuration>
</plugin>

   마지막으로 처음에 작성한 스크립트 파일들이 ${basedir}/deploy로 복사되도록 resources-plugin 설정도 추가했습니다. 원래 Maven Super POM에서 스크립트들의 디렉토리가 src/main/scripts로 지정이 되어 있는데, 어떤 플러그인에서 기본적으로 참조되는 지는 파악이 잘 안 됩니다. (아시는 분은 알려주셨으면 합니다.)


<plugin>
   <artifactId>maven-resources-plugin</artifactId>
   <version>2.3</version>
   <executions>
     <execution>
       <id>copy-resources</id>
       <phase>package</phase>
        <goals>
        <goal>copy-resources</goal>
        </goals>
        <configuration>
        <outputDirectory>${basedir}/deploy/</outputDirectory>
        <resources>
        <resource>
        <directory>src/main/scripts</directory>
       </resource>
       </resources>             
       </configuration>           
       </execution>
     </executions>
</plugin>

  이렇게 설정한 후 mvn package를 실행하면 ${basedir}/deploy 아래에 스크립트, 참조라이브러리, 직접 작성한 application의 jar파일들이 같이 생성됩니다. 이 디렉토리를 개발팀에서 쓰고 있는 배포방식을 이용해서 서버로 복사하게 합니다. Hudson에서 제공하는 FTP업로드 기능 등도 이럴 때 활용할 수 있겠습니다.

  배포된 서버에서 스케쥴링을 하고 싶다면 runJob.bat, runJob.sh나 이럴 이용한 스크립트를 crontab에 설정하면 됩니다. 실행되는 OS user나 JAVA_HOME 등의 환경변수값이 잘 넘어가는지 유의해야 합니다. 

  pom.xml파일이나 runJob.sh, runJob.sh의 스크립트는 imaso-batch.zip에 포함되어 있습니다.


- 정상혁, http://benelog.egloos.com


Trackback 0 Comment 2
2009/01/19 07:12

스프링배치 국내 자료 모음

정상혁

이미 35개 이상의 Accenture 고객사에 Spring batch가 적용되고 있다

스프링배치 연재(1) 배치처리의 특징

스프링배치 연재(2) 대용량 처리 배치 프로그램을 만들 때 유의할 점

스프링배치 연재(3) 스프링배치 프로젝트와 주요 기능들

스프링배치 연재(4) 스프링배치의 구조와 구성요소들

스프링배치 연재(5) ItemReader와 ItemWriter

스프링배치 연재(6) 플랫파일 읽기와 쓰기

스프링배치 연재(7) XML파일 읽기와 쓰기

스프링배치 연재(8) JDBC를 이용한 Cursor 기반의 DB 조회

스프링배치 연재(9) JobRepository

스프링배치 연재(10) JobLauncher와 Job, Step

스프링배치 연재(11) 재시작과 재시도

스프링배치 연재(12) 이벤트 처리, 유효성 검사, 변환, 기존 클래스 활용

스프링배치 연재(13) 스프링배치의 형제들

스프링배치 연재(14) 드라이빙 쿼리와 iBatis의 활용

스프링배치 연재(15) 하이버네이트 활용과 여러파일 읽기

스프링배치 연재(16) DB to XML 파일 만들기 예제

배치 어플리케이션 실행 스크립트와 빌드

 

박찬욱님

엘레강스한 배치 추상화 프레임웍 - 스프링 배치

[Beta 1.0]Spring Batch 프레임웍 레퍼런스 한글 편역 버전.

[Beta 2.0] Spring Batch 프레임웍 레퍼런스 한글 편역 버전.

[Beta 3.0] Spring Batch 프레임웍 레퍼런스 한글 편역 버전.

 

제 1부. 스프링 배치 기본 아키텍처와 잡(Job) 직접 실행해보기

제 2부. FlatFileItemReader와 그 친구들(파트1)

제 2부. FlatFileItemReader와 그 친구들(파트2) (소스 및 PPT)

제 3부. FlatFileItemWriter와 아이템 변환하기 (소스 및 PPT)

제 4부. StAX 기반 아이템 처리 (소스 및 PPT)

제 5부. 데이터베이스에 아이템 쓰고, 읽고~ (소스 및 PPT)

제 6부. 배치 반복 처리하기

 

Spring Batch 쓰임새 분석 - 단순한 배치 반복하기

Spring Batch 쓰임새 분석 - 자동적인 재시작

Batch Processing Strategies at Spring Batch 

스프링 배치's 액터(Actor)

 

Spring Batch 1.0에서 2.0으로 진화하기- 1. ItemReader/ItemWriter(1)

Spring Batch 1.0에서 2.0으로 진화하기- 1. ItemReader/ItemWriter(2)

Spring Batch 1.0에서 2.0으로 진화하기- 3. JobExecutionLisneter & 4. ItemProcessor

Spring Batch 1.0에서 2.0으로 진화하기- 5. Configuration

 

백기선님

The Domain Language of Batch - Spring Batch Chapter 2

ItemReader - Spring Batch Chapter 3

경구사님

Spring batch 개발환경 설정

 

김승권님

차세대배치시스템구축성공전략

 - [Spring batch]차세대 배치시스템 구축 성공전략 - JCO컨퍼런스

박재성님

Spring Batch 시작하기

 

KSUG포럼

SpringBatch에 대한 경험담을 듣고 싶습니다.

Spring Batch ItemReader 구현체에 대한 궁금증 

 

Trackback 0 Comment 0
2009/01/12 08:12

[Spring batch] 스프링배치 연재(16) DB to XML 파일 만들기 예제

  드디어 마지막회입니다. DB테이블에서 부모-자식 구조의 데이터를 읽어와서 하나의 XML파일로 만드는 작업을 구성해 봤습니다. 코드의 단순함을 위해서 전형적인 N+1쿼리 문제점을 가지는 예제를 만들었는데, 공개해 놓고보니 무턱대고 이런 방식을 따라할 사람이 있을까봐 걱정이 되기도 합니다. 예제의 방식보다 더 나은 성능이 필요한 경우에는 DB에서 join할 키값을 기준으로 정렬해서 테이블별로 한번씩만 조회한 다음에 sort merge방식으로 부모-자식 테이블간의 짝을 맞춰주는 방법을 쓸 수도 있습니다. 하이버네이트를 활용할 수 있다면 batch size 속성을 지정하는 것이 도움이 될 수 있는 상황도 있을 것입니다. (http://chanwook.tistory.com/710 참조) 저는 프로젝트에서 활용할 때, 기대 성능을 충족시키는데 지장이 없었던 작은 건수의 처리는 그냥 N+1쿼리방식을 쓰고 많은 건수를 읽는 작업은 sort merge방식을 사용했습니다.
  그리고 XStream으로 XML파일을 생성할 때 특별한 설정을 안 하면, 태그 명 중에 들어간 언더바 1개(_)가 언더바 2개(__)로 바뀌어버리는데, 처음 써보는 사람들이 공통적으로 겪을 수 있는 시행착오일 것입니다.

DB에서 2개 테이블을 엮어서 XML파일로 쓰기 예제

  DB에서 부모-자식 간의 관계로 된 테이블을 읽어서 하나의 XML로 만드는 작업은 실무에서 흔하게 만날 수 있는 배치처리 사례이다. 다음의 예제에서는 팀 테이블(team)과 선수(player)테이블에 DB에 있다고 가정하고 이를 하나의 XML로 만드는 작업을 진행해보고자 한다. 팀 테이블과 선수테이블은 당연히 1대 다 관계로 이루어져 있다. 테이블을 생성하고 테스트로 몇 개의 데이터를 넣어주는 스크립트가 첨부파일(imaso-batch.zip)에 포함되어 있다. (src/main/resources/data 폴더)

baseball.GIF 

 

 

  먼저 부모 테이블인 팀 테이블을 읽어오는 ItemReader를 작성해 보자. JdbcCursorItemReader클래스를 이용해서 쿼리와 그 결과를 Team의 도메인 오브젝트로 매핑할 수 있는 mapper를 지정한다. (리스트12)

 

<bean id="teamMasterReader" class="org.springframework.batch.item.database.JdbcCursorItemReader">
   <property name="dataSource" ref="dataSource" />
   <property name="mapper">
      <bean class="org.springframework.jdbc.core.BeanPropertyRowMapper" >
         <property name="mappedClass"  value="imaso.batch.domain.Team"/>
       </bean>
     </property>
     <property name="sql">
        <value> SELECT  team_id, team_name, symbol, rank FROM team</value>
     </property>
</bean>

리스트 12 : JDBC커서 방식으로 Team테이블 조회


  간단한 코딩을 위해서 mapper에 BeanPropertyRowMapper를 사용하고 mappedClass속성을 team테이블의 내용을 담는 도메인 오브젝트인 Team클래스로 지정했다. Team 클래스는 team 테이블의 컬럼명이 그 멤버변수로 선언되고 있고, getter,setter를 가진 단순한 클래스이다. Java의 일반적인 명명규칙에 맞추어서 언더바(_)가 없이 camel casing으로 표기되어 있다. BeanPropertyRowMapper는 언더바와 camel casing간의 변환을 자동으로 해 주기 때문에 team_id의 컬럼도 setTeamId메소드를 통해서 값이 채워지게 된다. 만약 성능을 조금이라도 향상시키고 싶다면 다소의 추가 코딩을 하더라도 별도의 RowMapper를 구현해서 사용하기 바란다.

  이제 team의 자식 테이블인 player를 읽을 차례다. 여러가지 방법이 있겠지만, DrvingQuery방식과 비슷하게 team 1건마다 그 팀에 소속하는 선수를 조회하는 쿼리를 던지는 방식을 사용해 보았다. 이를 위해 상위테이블만 읽어온 item object에서 그 자식 테이블을 읽어서 채워줄 수 있는 경우를 추상화하여 ItemWithChildrenReader라는 클래스를 작성해 보았다.

 

public abstract class ItemWithChildrenReader extends DelegatingItemReader{

  public Object read() throws Exception {
  Object item = super.read();
    if(item==null) return null;
      setChildren(item);
      return item;
   }
    protected abstract void setChildren(Object item);
   public ItemWithChildrenReader() {}

}

리스트 13: 부모-자식 테이블 조회기능을 추상화한 클래스

 

  이를 상속한 클래스에서 setChildren메소드를 구현하여 자식 테이블을 읽어서 넣도록 설계된 것이다.
  Team테이블에서 읽어온 값에서 Player테이블을 채워줄 수 있는 ItemReader는 리스트 14와 같이 구현하였다.

 

public class TeamReader extends ItemWithChildrenReader {
private RowMapper mapper;
private JdbcTemplate jdbcTemplate;
private String sql;
protected void setChildren(Object item) {
    Team team = (Team)item;
    Object[] params = new Object[]{team.getTeamId()};
    @SuppressWarnings("unchecked")
    List<Player> playerList = jdbcTemplate.query(sql, params, mapper);
    team.setPlayerList(playerList);
}
 // private 멤버 객체에 대한 setter 생략
}

리스트 14ㅣ Player를 읽어서 Team에 넣어주는 클래스

 

  setChild메소드 안에서 JdbcTemplate, RowMapper를 이용하여 player테이블의 건들을 읽어와서 team객체에 넣어준다. 만약 두 테이블을 연결시키는 키 속성명, 결과가 들어갈 속성명까지도 설정파일로 빼고 BeanUtils클래스의 setProperty, getProperty들을 활용한다면 보다 일반화시킨 클래스를 만들 수도 있다.
TeamReader의 설정에는 앞에서 나온 Team테이블을 읽어오는 TeamMasterRead를 itemReader속성으로 지정해 준다.

<bean id="teamReader"  class="imaso.batch.item.TeamReader">
   <property name="itemReader" ref="teamMasterReader" />
    <property name="sql">
       <value>
        SELECT team_id, player_id ,player_name, main_position
        FROM player  WHERE team_id = ?
  </value>
 </property>
<!-- mapper, jdbctemplate에 대한 설정은 생략 -->
</bean>

리스트 15 : TEAM과 PLAYER를 같이 읽어오는 클래스의 설정

 

  만약 위의 구현처럼 쿼리를 건마다 하나씩 던지고 싶지 않다면, 다소 구현이 복잡해 지더라도 team과 player 테이블 모두 team_id를 기준으로 정렬해서 조회한 후에 sorted merge 방식과 유사하게 양쪽 item들의 team_id값을 비교해 가면서 team에다 player를 붙여주는 구현도 가능하다.

  그 다음은 읽어온 내용을 XML파일로 쓰는 기능은 StaxEventItemWriter와 XStream 라이브러리를 같이 사용해서 구성했다. XStream 라이브러리를 보다 잘 활용하기 위해서 반드시 프로젝트가 의존하고 있는spring-oxm을 최신버전인 1.5.4로 참조해서 쓰기 바란다. 스프링배치의  샘플 프로젝트에서는 1.0.0버전을 참조하고 있는데, 당연히 최신버전에 비해 기능이 많이 빠져있다. 그리고 앞으로 설명한 아노테이션을 이용한 태그명 설정을 사용하기 위해서는 spring-oxm-tiger 라이브러리도 포함시켜야 한다. 예제에서 사용한 Maven2의 pom.xml파일은 첨부파일 내에 포함되어 있다.
 생성시킬 XML파일의 형태는 team태그 밑에 team 컬럼의 속성들이 들어가고 player테이블의 내용은 team 태그 밑에서 player태그로 여러 번 반복된다. (리스트 16)

<content>
<team> <team_id>1</team_id> <team_name>Lotte</team_name> 
    <symbol>Giants</symbol><rank>1</rank>
    <player>
      <playerId>0</playerId> <player_name>이대호</player_name>
      <main_position>3루수</main_position>
    </player>
    <player>....</player> <player>....</player>
   <team>...</team>   
   <team>...</team>
</content>

baseballXml.GIF

리스트 16 : 생성할 XML파일


앞의 teamReader에서 읽어온 내용을 쓰기 위한 StaxEventItemWriter을 리스트17과 같이 설정한다.

<bean id="teamXmlWriter"   class="org.springframework.batch.item.xml.StaxEventItemWriter">
    <property name="resource"  value="file:target/team.xml" />
    <property name="serializer" ref="teamSerializer" />
    <property name="rootTagName" value="content" />
    <property name="overwriteOutput" value="true" />
</bean>
<bean id="teamSerializer"  class="org.springframework.batch.item.xml.oxm.MarshallingEventWriterSerializer">
    <constructor-arg ref="teamMarshaller"/>
</bean>

리스트 17 : StaxEventItemWriter의 설정


 루트태그명을 rootTagName에서 content로 지정하고 xml을 생성하는데 필요한 요소들을 serializer속성-> MarshallingEventWriterSerializer 클래스-> teamMarshaller 빈으로 연결시켜 주는 것까지는 기본적인 사용법과 별차이가 없다.
여기서 도메인 오브젝트인 Team과 Player클래스에서 태그를 연결하기 위한 설정을 편하게 하기 위해서 아노테이션을 사용했다. AnnotationXStreamMarshaller를  사용하면 도메인 오브젝트 내에서 리스트18처럼 태그를 지정해 줄 수 있다.

public class Team {
@XStreamAlias("team_id") private int teamId;
@XStreamAlias("team_name") private String teamName;
private String symbol;
private int rank;
@XStreamImplicit private List<Player> playerList;

리스트 18 : 태그명을 어노테이션으로 지정


  @XStreamAlias 어노테이션을 이용해서 멤버변수의 이름과 태그명이 다른 경우에는 태그명을 명시해 준다. playerList필드처럼 Collection이면서, 그 필드의 이름 자체는 태그로 옮기어 지지 않을 경우에는 @XStreamImplicit 어노테이션을 이용한다. 즉, 우리가 만들고자 하는 샘픔에서 playerList속성과 대응되는 부분이 <playerList><player/><player/></playerList> 의 형식처럼 player태그를 playList태그가 한번 감싸고 있는 것이 아니고 바로 <player/>가 반복되는 형태이기 때문에 @XStreamImplicit가 붙어야 하는 것이다. Player클래스에서는 team_id 멤버 변수는 아예 태그로 옮기어 지지 않으므로 @XStreamOmitField 어노테이션을 붙여서 이를 명시했다. XStream의 annotation에 대한 자세한 설명은 http://xstream.codehaus.org/annotations-tutorial.html페이지를 참고하기 바란다.
  어노테이션을 사용하지 않는다면 AnnotationXStreamMarshaller의 상위클래스인  XStreamMarshaller 를 사용하고,  implicitCollection, omittedFields의 속성에 Map의 형태로 생략할 필드들을 지정할 수 있다.
  또 하나 주의할 점은 태그명에 언더바(_)가 들어가면 XStream에서는 디폴트로 그것을 언더바2개(__)로 바꾸어 준다는 점이다. 이 것은 XStream의 XmlFriendlyReplacer라는 클래스에서 하는 작업인데, 불행히도 현재의 AnnotationXStreamMarshaller클래스에서는 이 클래스를 바꿔치기 할 수 있는 기능이 없다. 그래서 AnnotationXStreamMarshaller를 상속하는 별도의 클래스를 만들고 XmlFriendlyReplacer를 끼워넣을 수 있도록 구현을 했다. 

public class ExtendedXStreamMarshaller extends AnnotationXStreamMarshaller{
private XmlFriendlyReplacer replacer;
protected void marshalSaxHandlers(Object graph,
ContentHandler contentHandler, LexicalHandler lexicalHandler)
      throws XmlMappingException {
SaxWriter saxWriter = new SaxWriter(replacer);
saxWriter.setContentHandler(contentHandler);
getXStream().marshal(graph, saxWriter);
}
//replacer에 대한 setter 생략
}

리스트 19 : XmlFriendlyReplacer 를 지정할 수 있는 확장 클래스


 XmlFriendlyReplacer상속한 DummyReplacer를 만들고 여기서는 언더바를 더블언더바로 바꾸는 동작을 수행하지 않도록 만든 후 이를 setter로 설정했다.

<bean id="teamMarshaller" class="imaso.batch.item.support.ExtendedXStreamMarshaller">
   <property name="annotatedClasses">
     <list><value>imaso.batch.domain.Team</value>
         <value>imaso.batch.domain.Player</value>
     </list>
   </property>
   <property name="replacer">
      <bean class="imaso.batch.item.support.DummyReplacer"/>
    </property>
</bean>

리스트 20 : Marshaller설정


  annotatedClasses속성으로 Team과 Player클래스를 지정해서 어노테이션을 XStream에서 인식할 수 있도록 해준다.
  StaxEventItemReader에는 이 밖에도 다양한 형태의 Xml 생성을 돕는 속성들이 있다. Root태그 밑에 여러 속성들이 있다면 rootElementAttributes 속성에 Map형식으로 이를 지정할 수 있다. 예들 들어 “<content id=”baseball”>”으로 XMl이 시작한다면 id가 key이고 baseball이 value인 Map을 지정해 주면 된다. 그리고 headerItems속성으로는 루트 태그 아래에 추가로 들어갈 다른 태그들을 넣을 수 있다. 이와 함께 XStream에서 제공하는 Converter인터페이스를 구현하고 XStreamMarshaller 의 converters 속성으로 그것을 등록해 주면, 객체가 태그로 바뀌는 형식을 보다 정교하게 구현할 수도 있다. 자세한 내용은 첨부파일에 있는 예제를 참고하기 바란다.

   ItemReader와 ItemWriter를 연결시키는 Step과 Job의 설정을 하면 모든 작업은 끝이 난다. 주의할 점은 SimpleStepFactoryBean에서는 ItemReader가 Writer가 바로 동시에 ItemStream이라면 자동으로 stream속성에 등록이 되는데, 다른 ItemStream객체가 있다면 따로 지정을 해 주어야 한다는 것이다. DelegatingItemReader안에 감싸져서 들어가는 itemReader와 같이, Step에 직접 등록되는 ItemReader가 아닌 경우도 여기에 해당한다. 리스트12와 15에서 보이듯이,  teamMasterReader도 teamReader에 감싸져 있는 클래스인데, itemStream인 JdbcCursorItemReader클래스이므로, Step설정에서 streams에 지정되어 있어야지 open,update,close와 같은 메소드들이 제대로 호출될 수 있다.

<bean id="teamDbToXmlStep" parent="simpleStep"> 
  <property name="itemReader" ref="teamReader"/>
  <property name="itemWriter" ref="teamXmlWriter"/>
  <property name="streams" ref="teamMasterReader"/>
</bean>

리스트21: Step의 설정

 

첨부파일

imaso-batch.zip

-정상혁,  http://benelog.egloos.com

Trackback 0 Comment 0
2008/12/30 09:12

올해의 스프링 기술 top5, 내년 유망 스프링 기술 top5 (안영회 편)

연말연시를 맞아서 KSUG 필진 중심으로 올해 두각을 나타냈던 스프링 관련 기술과 내년 떠오를 것으로 보이는 유망 스프링 기술을 각각 다섯 개씩 선정해보았습니다. 여러분들도 포럼을 통해 스스로 견해를 나눠보는 것이 어떨까요? 두 번째는 접니다.

올해의 스프링 기술 top5

1. Annotation 기반 설정(since Spring 2.5)
지난 Spring One Americas에서는 "설정은 XML 에서"라는 오랜 고정관념을 깨려는 듯 애노테이션 사용을 적극 장려하는 분위기였다. 설정 기반으로 애노테이션 기반으로 옮기는데 있어 오랫동안 J2EE/JEE 에서는 설정을 XML(EJB의 DD, Struts 등등)에서 했다는 점이 관성으로 작용한다. 그리고, 아직은 IDE 지원 역시 XML이 더욱 우위에 있다. 반면, Spring 2.5 부터 등장한 애노테이션 기반 설정은 light-weight 설정(?)을 가능하게 한다. Spring 3.0 에서 Java Config가 Core로 포함되면 애노테이션과 함께 시너지를 내는 모습을 볼 수 있지 않을까. 설정은 XML 영역이었던 시절이 현재형에서 과거형으로 바뀌어 가는 시점이다.[각주:1]

2. Spring dm Server
엔터프라이즈 시장에서 아직 OSGi 애플리케이션은 실험적인 단계로 볼 수 있다. Spring dm Server은 실험적인 단게에서 실용적인 단계로 견인하는 큰 축을 차지하고 있다. Spring dm Server가 없었더라도 엔터프라이즈 영역에서 OSGi의 발전이 이렇게 빨랐을까? OSGi에서도 POJO 프로그래밍을 고수할 수 있었을까? dm Server의 순위를 놓고 고민했는데 당장은 가시적인 효과가 나타나지 않았더라도 영향력에 있어서는 첫 손가락으로 꼽하도 과하지 않다.

3. Spring Batch
Spring Batch는 새로운 프로젝트이긴 하지만, Accenture의 오랜 노하우가 Spring의 옷을 입고 등장한 것으로 봐야 할 듯 하다. 몇 주전 필자의 소속회사에서 성공리에 국내 대형 금융사에 성공적으로 배치 개선 프로젝트를 끝냈다. 실험적인 것이 아니라 이미 운영 중인 애플리케이션에 도입했다는 점에서 국내 환경, 그것도 대용량 금융환경 적용 가능성을 검증한 것이라 볼 수 있다. 작년 말에는 소문만 무성했는데 한 해 만에 릴리즈하고, 사이트 적용이 가능해졌다니 놀랍도록 빠른 발전이다. 마침 KSUG에서 Spring Batch에 대한 benelog님의 시리즈를 연재 하고 있다.

4. Spring Web Flow 2.0
SWF가 2.0을 출시하면서 Spring Web Flow는 선택적 웹 기술에서 MVC의 중심으로 위상이 바뀐 듯 하다. Spring FacesSpring JavaScript 등의 웹 기반 프로젝트 모두는 SWF를 중심으로 MVC의 확장 기술로 위치하고 있다. AJAX 나 RIA 기술 등장으로 비롯한 다양한 웹 화면 요구가 SWF를 축으로 Spring에서도 구현되고 있다. SWF를 유망 기술로 꼽아야 하나 고민이지만, 2.0 릴리즈 이후 기반을 닦았다는 점에서 올해의 기술로 꼽았다.

5. Spring Integration
올해 처음으로 선을 보인 Spring Integration이 빠른 속도로 발전하고 있다. 아직은 incubator 수준이긴 하지만 Spring Integration Adapters 까지 생겨나 Spring Integration의 발전 가능성을 높여주고 있다. 아직 기능에 있어서는 부족한 모습이지만, SpringSource의 다양한 기술을 고려하면 향후 어떤 시너지를 창출할지 기대가 된다.


내년 유망 스프링 기술 top5

1. Spring Twin Server (Spring tc Server + Spring dm Server)[각주:2]
tc Server는 아직 데모밖에 보지 못한 상태지만, 파급효과에 대한 기대감에 있어서는 타의 추종을 불허한다. 과거 문제가 있어도 반쪽 EJB(?)를 그대로 쓰던 상황을 Spring이 타개했듯, 반쪽 WAS(?)를 쓰는 상황을 tc Server가 개선해주기를 바란다. 그리고, 올해의 top5에 선정했지만 dm Server 역시 내년에는 더욱 발전하여 tc Server/dm Server가 Application Server 시장에도 일대 혁신을 가져오길 기대한다.

2. Grails
Spring One Americas 2008에 참석하기 전까지는 SpringSource의 G2One 인수가 얼마나 큰 의미를 지니는지 알지 못했다. Grails는 Spring/Hibernate의 기반을 똑같이 활용하면서 완전히 새로운 API 스타일을 추가한 격이다. DSL 개발 등을 통해 개발 과정을 고도화 한다면, 엔터프라이즈 환경에서도 요구사항 반영 주기/시스템 개선 주기를 혁신적으로 개선할 수 있을 가능성을 보여주고 있다. 개인적으로 내년도 가장 흥미롭게 연구해볼 주제 가운데 하나다.

3. Spring 3.0
2.5, 3.0 대신에 3.0, 3.5 라고 하는 것이 어땠을까 할만큼 완전히 새로운 면모보다는 2.5의 일대 개선처럼 보인다. 이러한 면에서 Spring 커뮤니티의 지속적인 개선을 더욱 높이사게 된다. 물론 영원하지야 않겠지만, 내년 이맘때에도 지금처럼 Spring의 꾸준한 발전을 볼 수 있기를 기대한다.

4. Spring Security 2.5
benelog님 말처럼 가장 복잡한 영역 가운데 하나인 보안 프로그래밍 쪽에 단비와 같은 프레임워크가 Spring Security 이다. 엔터프라이즈 프로그래밍에 국한해서 보면, 확장성에 있어서는 거의 독보적인 솔루션이 아닌가 싶다. Acegi 1.5 에서 Spring Security 2.0 개선할 때는 Spring 2.0의 스키마 기반 설정을 대폭 보강하더니 2.5에서는 Spring 3.0과 궤를 같이 하여 애노테이션 및 EL 활용에 대한 밀착 연계를 제공한다. 출시 시점도 Spring 3.0에 맞춰져 있다.

5. Consolidation 솔루션
다소 무리한 분류라 할 수 있지만, terracotta 류의 클러스터 솔루션과 플랫폼 가상화 솔루션 등을 묶어서 consolidation[각주:3] 솔루션으로 분류했다. 기존에 Spring의 영역은 "개발"에 국한했었지만, 캐시에서 클러스터 솔루션으로 변모한 Spring 유관제품이 등장하더니 VMWare와 손잡고 새 제품 출시를 준비중이다. Spring Portfolio의Consolidation 시장 진출은 "Ubiquitous Spring" 현상을 강화하는 전기가 될 것이다.

  1. 참고로 Spring 2.5 릴리즈는 작년 말이다. [본문으로]
  2. 둘은 다른 시장을 대상으로 하면서도 같은 목적과 기반을 갖고 있어 Twin 서버라고 지칭했지만, 필자 임의로 붙이 이름이다. :) [본문으로]
  3. IFRS 회계 국경이 사라진다 에서 '연결과 통합'이라고 번역했다. [본문으로]
Trackback 0 Comment 4
2008/12/30 07:53

[Spring batch] 스프링배치 연재(15) 하이버네이트 활용과 여러파일 읽기

 스프링배치에서 제공하는 하이버네이트 지원 클래스들을 소개합니다. StatelessSession의 특징에 대해서는 http://chanwook.tistory.com/396를 참조하시기 바랍니다.


하이버네이트의 활용

  HibernateCursorItemReader 를 사용하면 하이버네이트를 사용하면서도, 지난 연재에서 소개했던 JdbcCurItemReader와 유사한 커서방식의 조회가 가능하다. 설정의 예는 리스트 8에 나와있다.

<bean id="hibernateItemReader"   class="org.springframework.batch.item.database.HibernateCursorItemReader">
    <property name="useStatelessSession" value="true" />
    <property name="queryString" value="from player" />
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

리스트 8 : 하이버네이트를 이용한 조회


  sessionFactory 속성은 스프링에서 기본적으로 제공하는 LocalSessionFactoryBean 를 이용해서 설정한다. useStatelessSession 속성에 따라서 상태를 가지거나 안 가지는 Session이 생성된다.  useStatelessSession과 queryString이 하이버네이트의 코드와 어떻게 연결되는지는 리스트9에 있는 Query를 생성하는 부분을 보면 알 수 있다. StatelessSession이라면 하이버네이트에서 제공하는  Cache 와 Dirty체크 기능을 쓰지 않게 된다.


private Query createQuery() {
  if (useStatelessSession) {
   statelessSession = sessionFactory.openStatelessSession();
   return statelessSession.createQuery(queryString);
  } else {
  statefulSession = sessionFactory.openSession();
  return statefulSession.createQuery(queryString);
  }
}

리스트 9 : 하이버테이트와 연결되는 부분


 하이버네이트를 이용해서 DB에 자료를 저장하고 싶을 때도 HibernateAwareItemWriter라는 클래스도 도움을 줄 수 있다. 리스트9에 나와있듯이, 이 클래스에도 마찬가지로 sessionFactory를 속성으로 지정하고, 다른 하이버네이트를 쓰는 ItemWriter를 delegate에 연결시킨다.

<bean id="hibernateItemWriter"
  class="org.springframework.batch.item.database.HibernateAwareItemWriter">
  <property name="sessionFactory" ref="sessionFactory" />
  <property name="delegate" ref="playerWriter" />
</bean>

리스트 10 : 하이버네이트를 인식하는 ItemWriter

 

  HibernateAwareItemWriter는 트랜잭션의 한 묶음이 한꺼번에 commit 되었을 때 실패가 일어난다면, 어떤 item이 실패인지 알아보기 위해 실패한 묶음을 다시 한건 한건 쓰기 시도를 해준다. Jdbc의 batchUpdate를 이용하는 ItemWriter인 BatchSqlUpdateItemWriter의 경우에도 마찬가지의 흐름을 가진다.


여러 파일 읽기

  앞 선 연재에서 소개한 FlatFileItemReader 같은 파일읽기 클래스들은 읽을 파일을 resource속성을 통해서 지정한다.  실무에서는 읽어서 처리할 파일이 하나가 아니고 특정 디렉토리에 있는 파일 전체나 아니면 특정 확장자, 이름패턴을 가지고 있는 경우가 대부분일 것이다. MultiResourceItemReader클래스는 와일드 카드등을 이용해서 여러 파일들을 한꺼번에 지정할 수 있다. 리스트 11과 같이 resources 속성으로 파일들을 읽을 패턴을 지정하고, delegate속성에 그 resource를 읽을 itemReader를 연결시켜 준다.
<bean id="multiResourceReader" class="org.springframework.batch.item.file.MultiResourceItemReader">
  <property name="resources" value="classpath:data/multiResourceJob/input/file-*.txt" />

  <property name="delegate" ref="flatFileItemReader" />
</bean>

리스트 11 : 여러파일 읽기


정상혁, http://benelog.egloos.com

Trackback 0 Comment 0
2008/12/29 08:53

올해의 스프링 기술 top5, 내년 유망 스프링 기술 top5 (benelog 편)

연말연시를 맞아서 KSUG 필진 중심으로 올해 두각을 나타냈던 스프링 관련 기술과 내년 떠오를 것으로 보이는 유망 스프링 기술을 각각 다섯 개씩 선정해보았습니다. 여러분들도 포럼을 통해 스스로 견해를 나눠보는 것이 어떨까요? 첫 번째 주자는 올해 주옥 같은 Spring Batch 연재를 올려주신 benelog 정상혁님입니다.

2008 올해의 스프링기술 Top 5

5. Spring Security

 권한,인증,보안 등의  모듈의 설계는 어느 시스템이나 필수적이고, 많은 고려 사항이 들어가야 하는 부분입니다.  그래서, 경험이 있는 개발자라면 이 것이 원래 복잡한 영역이라는 것에  동의할 것입니다.  이 권한 등의 관련 모듈은 유연하면서 충분한 기능을 담도록 만들기가 쉽지 않고, 매번 새로운 시스템마다 반복적으로 설계, 개발되는 경우도 많습니다. 그렇기에 이 영역에서 Spring Security의 존재가 가치있게 느껴집니다. Spring이 간단한 개발을 괜히 복잡하게 만드는 것이 아니고, 필수적으로 복잡한 요구사항이 충족되어야 하는 영역을 이미 만들어진 모듈을 쓰면서도 더 유연한 구조를 제공을 한다는 것을 Spring Security를 통해서 보여주고, 공감을 이끌어낼 수 있다고 생각합니다. 그런 의미와 2008년 들어 더욱 빨라지고 있는 것으로 보이는 발전속도, 적용 사례의 증가가 돋보이기에 2008년의 Spring 기술중 하나로 선정했습니다.


4. SpringSourceTool Suite

  SpringSourceTool Suite는 스프링이 이제 개발자의 더 가까운 곳에서 더 자세히 개발을 도와주는 역할을 주겠다는 의미로 다가옵니다. 그리고 스프링의 상용제품 출시를 본격적으로 알리는 신호탄으로, 앞으로의 스프링소스의 사업모델의 측면에서 보아도 이 제품이 중요한 분기점의 의미가 되지 않나하는 생각이 듭니다.


3. Spring batch

  KSUG 블로그에 오시는 분들은 잘 아시다시피, 제가 올해 가장 큰 관심을 가졌던 배치 프레임웍입니다. Accenture의 현장경험이 잘 녹아들어가고 Spring기반의 기술이 이를 뒷받침해서 본격적으로 Java 배치프레임웍의 논의를 불러일으킨 기술이라고 생각합니다. 배치처리에 어떤 기능들이 필요할 지를 보다 고민하는 계기가 되고, 경험있는 개발자의 처리 방식을 참고하고 그대로 사용할 수도 있다는 것에서 스프링배치는 큰 의미가 있습니다. 아직 젊은 프로젝트라서 1.X의 버전에서는 분산처리 같은, 성숙한 유사 모듈에 있는 기능들이 빠진 것들도 보이지만, 내년 2.0 발표 등으로 보다 강력한 프레임웍으로 발전해 나갈 것으로 예상됩니다.


2. Spring 2.5

 Spring 2.5가 발표된 것은 작년이였지만, 본격적으로 주변에서 적용되는 것을 본 것은 올해라고 느껴집니다. 개발자들이 하위 호환성에 대한 걱정을 크게 하지 않으면서 기존 모듈의 의존성을 Spring 2.0에서 2.5로 업그레이드하는 사례를 여러번 봤는데, 이런 현상은 Spring에 대한 신뢰성이 깊어졌으면서도 그 발전 속도에 개발자들이 적응을 하게 된 것 같다는 의미부여를 하고 싶습니다. 



1. Spring DM Server

  이 기술의 발표 소식을 듣는 순간 과연 스프링의 영역이 어디까지 뻗어나갈까 하는 감탄이 들었습니다. 그리고 앞으로 퍼져나갈 OSGi 세상에서도 Spring이 단순 프레임웍 이상의 큰 역할을 할 것이라는 확신을 심어준 사건이였죠.



2009 유망 스프링 기술 Top

5. Spring Web Flow

javascript, JSF 지원기능 등 더욱 확장된 영역으로, 이제는 앞으로는 기본 웹개발은 SpringMVC, 보다 많은 기능이 필요한 웹개발은 Spring Web Flow이 맡게 되지 않을까하는 예감이 듭니다.

4. Spring Integration

  현재 1.0 마일스톤 버전이 발표되어 있습니다. 1.0 최종버전이 나오면 본격적으로 Spring Integration을 적용해보고 싶어하는 개발자가 많을 것 같습니다. 데이터 연계(Integration) 모듈도 어느 시스템에나 있는 것이고, Spring Integration은 다양한 종류의 자원들을 동일한 방식으로 연결시켜주는 기능을 제공하므로, 많은 기대를 가지게 합니다.

3. Spring DM

 아마도 내년이 Spring DM의 본격적인 대중화 시기가 되었으면 합니다. 대부분의 개발자들에게 낯선 OSGi 세계에서도 스프링이 든든한 길잡이가 되어줄 것으로 믿습니다.

2. Grails

  이미 JVM위에서 돌고 있는 스크립트 언어가 200여가지라고 하죠. (http://www.is-research.de/info/vmlanguages/ ) 필요한 영역에 따라 JVM위에서 돌아가는 Script언어를 사용하게 될 것이라는 예상은 몇년전부터 있어왔는데, 아직까지 그 기대에 비하면 적용된 곳이 많지 않아 보입니다. 그래도 JVM 위의 Script언어 중 가장 많이 알려진 Groovy 바탕 위에서 Ruby on Rails의 뜨거운 열풍을 탄 Grails를 SpringSource까지 밀어준다는 소식은 Java web개발의 대전환기가 멀지 않았다는 느낌을 들게 합니다.

1 .Spring 3.0

  내년에는 Spring 3.0 정식버전이 발표될 예정으로 있습니다. 가장 영향력이 큰 Core 모듈이자, 어떤 기술들과 비교해도 스프링의 발전의 속도가 빠르다는 것을 확실히 느끼게 해주는 부분입니다.
Trackback 0 Comment 0
2008/12/27 21:11

[Spring batch] 스프링배치 연재(14) 드라이빙 쿼리와 iBatis의 활용


 이번 연재분에서는 드라이빙 쿼리 조회 방식과 그 상세조회를 iBatis로 할 수 있는 방법을 설명했습니다. 

드라이빙 쿼리 방식의 조회

  앞선 연재에서 JdbcCursorItemReader를 이용한 Cursor방식의 조회에 대해서 소개했었다. 전체 데이터를 한꺼번에 메모리에 올리지 않기 때문에 대용량을 처리할 수 있는  방식이지만, DB2와 같이 비관적인(pessimistic) 락을 주로 사용하는 DB에서는 주의해서 사용해야 한다. Pessimistic lock은 레코드가 변경되지 않을 때도 락이 걸릴 수 있는데, Cursor를 사용하는 처리방식이 시간이 오래 걸리는 경우라면 오랫동안 lock을 유지할 수 있는 위험성이 생긴다. 이 것이 염려되는 상황이라면 한꺼번에 키 값만을 먼저 읽어서 메모리에 올린 후 한번에 조회하는 드라이빙 쿼리방식을 검토해 보아야 한다.  한 편으로는 이 방식은 전체 건수+1 만큼의 쿼리를 DB에 요청하게 되어 있으므로, Cursor 방식에 비해 전체 처리시간은 확연히 길어지게 된다. 사용하는 DB와 어플리케이션의 특성을 감안하고, 필요하다면 DBA나 같은 DB를 사용하는 다른 개발자와 충분한 상의를 해보도록 하자. 그리고, 전체 조회건수가 엄청나게 많아서 키값만을 메모리에 한번에 올리는 것조차 불가능한 상황이 올 수 있는지도 검토해보아야 할 것이다.

  스프링배치에서는 DrivingQueryItemReader 클래스로 드라이빙 쿼리방식을 사용할 할 수 있다. 이 클래스의 keyCollector라는 속성이 이름 그대로 아이템의 키값을 먼저 읽어오는 역할을 한다. 이 속성은 리스트1과 같은 인터페이스로 선언되어 있다.

public interface KeyCollector {
  List retrieveKeys(ExecutionContext executionContext);
  void updateContext(Object key, ExecutionContext executionContext);
}

리스트 1 : KeyCollector 인터페이스

  KeyCollector 의 retrieveKeys메소드에서는 키값을 읽어와서 List형태로 반환하는 역할을 하고, updateContext 메소드에서는 작업이 중간에 실패하면 재시도를 위한 정보를 저장하는 작업을 수행하게 된다. 이런 처리를 위해 구현 클래스인 SingleColumnJdbcKeyCollector클래스에서는 재시도 시 실행시키는 쿼리를 담기 위한 restartSql 속성도 가지고 있다.

  DB에  player 라는 테이블이 있고, Id라는 컬럼이 이 테이블의 주키값이라면 리스트2와 같이 드라이빙 쿼리를 이용하는 설정을 할 수 있다.

<bean id="playerReader"
  class="imaso.springbatch.PlayerReader">
  <property name="keyCollector">
    <bean class="org.springframework.batch.item.database.support.SingleColumnJdbcKeyCollector">
      <property name="sql">
         <value> SELECT id FROM player  ORDER BY id
     </value>
     </property>
     <property name="restartSql">
         <value> SELECT id FROM player WHERE id > ? ORDER BY id
         </value>
      </property>

      <property name="keyMapper" ref="playerMapper">
      <property name="jdbcTemplate" ref="jdbcTemplate">
    </bean>   
  </property>
</bean>

리스트 2 : 드라이빙 쿼리 방식의 조회 설정

 

  첫째 줄의 playerReader빈의 클래스로 지정된 PlayerReader 클래스는 리스트3과 같이 DrivingQueryItemReader를 상속한 클래스의 read메소드 안에서 상세조회 기능을 만들어 준다.

public class PlayerReader extends DrivingQueryItemReader {
    public Object read(){
        Object item = super.read();
        //읽어온 item의 상세조회를 하기 위한 작업을 수행
}

리스트 3 : 드라이빙 쿼리를 바탕으로 상세조회를 하는 클래스

  jdbcTemplate속성은 DataSource가 그 내부에 연결되어 있는 JdbcTemplate 클래스 설정 bean을 지정한다.  keyMapper는 DB에서 조회된 키값인id를 Player테이블을 위한 도메인 오브젝트로 매핑해주기 위한 클래스로 스프링의 RowMapper 인터페이스를 구현하면 된다.


IBatis의 활용

  IbatisDrivingQueryItemReader클래스는 item의 상세 조회를 iBatis를 통해서 할 수  있게 한다. sql쿼리를 직접 지정하지 않고 iBatis의 sql설정파일에 있는 쿼리의 id를 넘기는 것이다. 앞에선 본 playerReader 예제를 iBatis를 활용한 클래스로 재구성하면 리스트4와 같다.

 

<bean id="playerReader"   class="imaso.springbatch.PlayerReader">
  <property name="keyCollector" ref=”playerKeyCollector”>
  <property name="detailsQueryId" value=" selectPlayerDetail "/>
  <property name="sqlMapClient" value=" sqlMapClient "/>
</bean>

리스트 4 : IBatis를 이용한 상세조회

  detailsQueryId에 들어가는 속성이 sqlMap 설정 파일에 들어가 있는 쿼리의 id이고, sqlMapClient 는 iBatis에서 쓰는 DB접근을 위한 클래스이다. 도메인 오브젝트와의 매핑 등 쿼리실행에 대한 것들은 iBatis의 설정파일 내에서 지정된다.

  웹Application에서 스프링과 iBatis를 연결시킬 때와 마찬가지로, sqlMapClient와 Datasource의 설정은 리스트5와 같이 SqlMapClientFactoryBean을 활용하면 된다.

<bean id="sqlMapClient"

   class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
  <property name="configLocation" value="classpath:datasource/sql-map-sample.xml" />
  <property name="dataSource" ref="sampleDataSource"/>
</bean>

<bean id="sampleDataSource" class="org.apache.commons.dbcp.BasicDataSource">
  <property name="driverClassName" value="${batch.jdbc.driver}" />
  <property name="username" value="${batch.jdbc.user}" />
  <property name="password" value="${batch.jdbc.password}" />
</bean>

리스트 5 : iBatis 관련 스프링 설정

  ${batch.jdbc.driver}처럼 변수로 지정된 부분은 스프링의 PropertyPlaceholderConfigurer클래스를 이용해서 다른 프로퍼티 파일에 지정된 것을 가지고 오거나 Maven의 resource filtering 기능을 이용해서 빌드 시에 개발,운영 등 각 환경에 맞는 값이 엮여지도록 할 수 있다.
KeyCollector를 사용할 때도, IBatisKeyCollector를 통해서 iBatis의 설정파일 속에 있는 쿼리를 가지고 올 수 있다. drivingQueryId라는 속성에 키값만을 조회할 쿼리의 id를 지정해주면 된다.

<bean id=" playerKeyCollector " class="org.springframework.batch.item.database.support.IbatisKeyCollector">
  <property name="drivingQueryId" value="selectAllPlayerId" />
  <property name="sqlMapClient" ref=" sqlMapClient " />
</bean>

리스트 6 : iBatis를 이용한 드라이빙 쿼리

  마찬가지로 DB에 데이터를 입력할 때에도 유사하게 iBatis를 쓸 수 있다.  필자가 실무에서 활용하기 위해 만들어본 SimpleIbatisItemWriter 라는 클래스가 리스트7에 나와있다.

public class SimpleIbatisItemWriter extends AbstractItemWriter{
  private String writingQueryId;
  private SqlMapClientTemplate sqlMapClientTemplate;       
  public void write(Object item) throws Exception {

    sqlMapClientTemplate.insert(writingQueryId,item);
  }
  public void setSqlMapClient(SqlMapClient sqlMapClient) {
    sqlMapClientTemplate = new SqlMapClientTemplate(sqlMapClient);
  }
  //writingQueryId setter 메소드 생략
}

리스트 7 : iBatis를 활용한 DB입력

  IBatisKeyCollector와 유사하지만writingQueryId에 insert문이 들어가 있는 쿼리의 id를 지정해 준다는 것만 차이가 있다.

정상혁, http://benelog.egloos.com

Trackback 0 Comment 0
2008/12/16 07:24

[Spring batch] 스프링배치 연재(13) 스프링배치의 형제들

이번 연재분은 사실 마이크로소프트웨어지 연재 시에 분량을 잘 못 맞추어서, 추가 원고 요청을 받아서 급하게 넣은 내용들이였습니다. 스프링 포트폴리오 중에서는 Spring Integration이 앞으로도 계속 스프링배치와 밀접한 관계를 맺을 것으로 보이기에 스프링배치 사용자도 계속 주목해야할 프로젝트라고 생각합니다. 그리고 ETL툴인 Kettle에 대해서는 연재 분량이 다 올라간 후에 보다 자세히 소개드려고 합니다.

다른 스프링 프로젝트들

  지금 시점에서 스프링이 커버하는 넓은 영역들은 '프레임웍'이라는 말만으로는 다 표현하기가 벅차다고 느껴진다.  SpringWebFlow, SpringSecurity, SpringDM 등이 포함된 스프링 포트폴리오들의 진용을 보면,  안 건드리는 영역이 어떤 것이 있을까하는 생각이 든다.  이 중 스프링배치와 연관성을 맺고 있는 프로젝트는 스프링 인테그레이션(Spring-Integration), 스프링웹서비스(SpringWebService), 스프링 어플리케이션 플랫폼(Spring Application Flatform)이 있다.

  스프링 인테그레이션은 기업환경의 데이터 연계 작업을 돕는 프레임웍이다. 복잡한 연계방식을 추상화 시켜서 비동기 메시지 기반으로 구성할 수 있게 한다. JMS, RMI, File, Http, Ftp, Web service 등의 연결방식이 같은 인터페이스로 추상화되어 제공되는 것이다. 배치처리도 데이터 연계를 위한 목적으로 많이 쓰이기 때문에 당연히 스프링배치와 스프링 인터그레이션의 영역은 겹치는 곳이 있다. 아직 정식판에 포함되지는 않았지만 스프링배치와 스프링 인테그레이션을 결합한 프로토타입 코드도 나와있다. [각주:1]앞으로 버전업이 계속 될수록 두 프레임웍은 더욱 긴밀한 사이를 유지할 것으로 보인다. 스프링배치 2.0에서는 스프링 인테그레이션을 이용해서 원격지에서 Item을 쓸 수 있는 Remote Chunking이라는 기술을 지원할 예정이다.[각주:2]

  스프링 웹서비스는 SOAP을 사용하는 Web servcie 를 쉽게 만들 수 있는 프레임웍이다.  다른 웹서비스 구현 프레임웍에 비해서도 짧은 코드로 XML 웹서비스를 쓰는 어플리케이션을 구성할 수 있고, Spring MVC를 아는 사람에게는 더욱 친숙하게 느껴질 수 있는 구조로 되어 있다. 스프링배치에서 XML파일은 스프링웹서비스에 포함되어 있는 Spring OXM(Object-XML-Mapping) 을 이용해 처리하는 것이 가능해서 보다 많은 유연하고 많은 라이브러리들을 사용할 수 있다. 스프링 3.0에서는 Spring OXM이 보다 상위모듈에 포함될 수도 있다고 한다. 그리고 스프링 인테그레이션에서도 Web service 연결부분은 스프링 웹서비스에 위임하고 있다.

  OSGi 기반의 환경을 제공하는 스프링 어플리케이션 플랫폼에서도 스프링배치가 OSGi 번들로 실행될 수 있다.[각주:3] 향후 버전에서도 더욱 배치에 특화된 기능들이 추가될 것이라고 한다.

  한편, 스프링배치의 Retry, Repeat 개념들도 보다 일반화 되어 스프링3.0에서는 코어 모듈로 들어갈 수 있다는 소문도 들린다.  이렇듯 스프링 포트폴리오들은 서로 영향을 주고 받으며 빠른 속도로 발전하고 있고, 이는 개발자들에게는 보다 풍족함을 느끼게 해 줄 것으로 기대된다. 앞으로 2~3년 후에 스프링과 그로 인한 자바 세계가 어떻게  변해있을지 생각하는 일은 버거운 일이지만 즐거운 상상이다.

 ETL 툴

   스프링배치조차도 ETL(Extract, Transform, Load)툴로 분류되기도 하지만, Java 세계에도 이전부터 오픈소스 ETL툴이 있어 왔다.

  Kettle(http://kettle.pentaho.org/)은 이중 가장 오랜역사와 많은 사용자를 가지고 있는 툴로, Pentaho 라는 회사에서 Pentaho Data Integration이라는 이름으로도 배포된다. 별도의 GUI툴을 제공하고, Job의 설정 내용을 XML이나 DB로 저장할 수 있다. 특히 DB를  Job의 내용을 담는 저장소로 활용하면, 별도의 프로그램 배포작업이 필요없고, 여러명사이에 공동작업에 유리한 점이 있다.

  Talend Open Studio(http://www.talend.com/ )은 Jasper사에서도 Jasper ETL이라는 이름으로 제공되고 있다. Eclipse plug-in 기반의 툴이 제공되고, 최종 산출물로는 Java나 Perl의 코드가 생성된다.
  두 제품이 Java 오픈소스 ETL툴의 양대산맥이라고 할 수 있고, Open소스 기반이지만 일부 유료기능이나 교육, 컨설팅 등으로 수익을 얻는 사업모델을 가지고 있다. 그 툴다 리포팅툴 등을 포함한 Business Intelligence 패키지의 일부로 제공된다는 것도 공통점이다. Kettle이 무료 기능의 폭이 더 넓은 편이고 Talend Open Studio는 국내에도 제휴된 기술 지원 업체가 있다는 장점이 있다. 스프링배치에서 다루고 있는 파일 형식들(XML,Flat file)과 프로토콜(FTP, HTTP)가 대부분 지원되며, 여러대의 컴퓨터에서 하나의 작업을 병렬실행하는 것도 가능하다.

  스프링배치와 이런 툴들은 어떤 장단점이 있을까? Java와 스프링개발에 익숙한 개발자가 많고, 정교한 흐름처리, 확장성이 필요하다면 스프링배치가 유리할 것이고, 시스템에서 필요한 요구사항들이 ETL툴이 제공하고 있는 기능들에 잘 맞아떨어지는 경우에 GUI로 된 편한 작업환경을 누리고 싶다면 Kettle이나 Talend Open Studio 같은 툴이 나을 것이다.


- 정상혁 (http://benelog.egloos.com)


Trackback 0 Comment 0