예제는 기본적인 JobReposiotry, JobLauncher, TransactionManger, Job, Listener의 관계를 설명하기 위해 작성되었습니다.
보다 상세한 내용은 다음의 블로글을 참조하세요.
1. Spring Batch Basics
2. Understanding Job and Step Configuration in Spring Batch
예제의 각 파일에 대한 기본적인 설명은 다음과 같습니다 (소스 코드는 첨부 파일을 다운로드 받으세요)
1. config/spring-context.xml: Spring Batch Infrastructure 설정.
2. com.hjh.batch.HelloWroldTasklet: 'Spring Batch Hellow World Tasklet!'를 출력하는 첫번째 커스텀 Tasklet (Job을 구성하는 첫번째 Step).
3. com.hjh.batch.GoodbyeTasklet: "Goodbye Spring Batch!"를 출력하는 두번째 커스템 Tasklet (Job을 구성하는 두번째 Step).
4. com.hjh.batch.JobListener - 커스텀 JobExecutionListener 구현체.
5. com.hjh.batch.StepListener - 커스텀 StepExecutionListener 구현체로 HelloWorldTasklet 및 GoodbyeTasklet의 리스너로 등록.
6. com.hjh.batch.JobRuntime - 커스텀 Job 실행 클래스.
7. com.hjh.batch.Launcher - main() 메소드가 있는 클래스.
1. spring-context.xml 설정
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:batch="http://www.springframework.org/schema/batch" xmlns:task="http://www.springframework.org/schema/task" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<!-- 1. Job Repository - IN-MEMORY Repository --> <bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean"> <property name="transactionManager" ref="transactionManager" /> </bean>
<!-- 2. Launch Job from a Repository --> <bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher"> <property name="jobRepository" ref="jobRepository" /> </bean>
<!-- 3. Defines 2 steps of a Job --> <bean id="helloTask" class="com.hjh.batch.HelloWorldTasklet" />
<bean id="goodbyeTask" class="com.hjh.batch.GoodbyeTasklet" />
<!-- 4. Register Job Listener --> <bean id="jobListener" class="com.hjh.batch.JobListener" />
<!-- 5. Register Step Listener --> <bean id="stepListener" class="com.hjh.batch.StepListener" />
<!-- 6. Finally Job Defined --> <batch:job id="simpleJob"> <batch:step id="helloStep" next="goodbyeStep"> <batch:tasklet ref="helloTask" /> <batch:listeners> <batch:listener ref="stepListener" /> </batch:listeners> </batch:step> <batch:step id="goodbyeStep"> <batch:tasklet ref="goodbyeTask" /> <batch:listeners> <batch:listener ref="stepListener" /> </batch:listeners> </batch:step> <batch:listeners> <batch:listener ref="jobListener" /> </batch:listeners> </batch:job>
<!-- 7. Custom Job Launcher Class --> <bean id="runtime" class="com.hjh.batch.JobRuntime"> <property name="jobLauncher" ref="jobLauncher" /> <property name="job" ref="simpleJob" /> </bean>
</beans> |
1. JobRepsitory를 설정합니다. 예제에서는 In-Memory persistent store을 사용합니다. 이때 TransactionManager로 ResourcelessTransactionManager를 사용합니다. 실제 프로덕션 확경에서는 jdbc persistent store 사용이 바람직합니다.
물론 비즈니스 환경에 문제가 없다면 in-momory persistent store를 사용하셔도 무방합니다.
2. 실제로 Job을 실행하기 위한 JobLauncher를 설정합니다. Job을 실행하기 위해 유효한 JobExecution 정보을 업데이트하기 위한 JobRepository를 셋팅합니다.
SpringBatch의 SimpleJobLauncher는 JobLauncher 인터페이스의 구현체로써, Job을 실행하기 위해 Spring Core 패키지의 TaskExecutor를 내부적으로 사용합니다. 디폴트로 SyncTaskExecutor가 사용되는데, launcher를 콜한 같은 Thread에서 Job이 실행된다는 의미입니다. 따라서, asynchronous(비동기적) Job 실행을 위해서는 비동기적 목적의 TaskExecutor(SimpleAsyncTaskExecutor)를 설정하여야 합니다.
3. Job을 구성하는 첫번째 Step인 HelloTasklet와 두번째 Step인 GoodbyeTasklet을 설정합니다. 예제에서는 ItemReader / ItemWriter를 사용하지 않음으로 Tasklet 인터페이스를 구현하였습니다.
첫번째 Step HelloTasklet이 성공적으로 종료하면, next element 설정에 의해 두번째 Step GoodbyeTasklet이 실행되게 설정합니다.
만약, 하나의 Step이라도 실패하게 되면, Job 실행은 실패하게 됩니다.
4. JobExecutionListener 인터페이스의 커스텀 구현체인 JobListener을 설정합니다.
5. StepExecutionListener 인터페이스의 커스텀 구현체인 StepListener을 설정합니다.
6. JobLauncher에 의해 실행될 Job을 구현합니다.
Job은 3번에서 설정된 두개의 Step으로 구성하며, 각각의 Step은 5번에서 설정된 리스너를 등록합니다.
그리고, Job에도 4번에서 설정된 리스너를 등록합니다.
7. 최종적으로 Job을 메인메소드에서 실행하기 위한 커스텀 launcher를 설정합니다.
2. HelloWorldTasklet 작성
package com.hjh.batch;
import org.apache.log4j.Logger; import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus;
public class HelloWorldTasklet implements Tasklet {
private static final Logger LOGGER = Logger.getLogger(HelloWorldTasklet.class);
@Override public RepeatStatus execute(StepContribution arg0, ChunkContext arg1) throws Exception {
LOGGER.info("Spring Batch Hellow World Tasklet!");
return RepeatStatus.FINISHED; }
} |
Tasklet(Step)이 실행되었을때, 단순히 "Spring Batch Hellow World Tasklet! 메시지를 콘솔에 출력합니다.
리턴값으로 RepeatStatus.FINISHED 값이 설정되었습니다. 만약, RepeatStatus.CONTINUABLE이 셋팅되 되면 두 번째 Step으로 이동하지 않고 반복적으로 HelloWorldTasklet이 실행됩니다.
3. GoodbyeTasklet 작성
package com.hjh.batch;
import org.apache.log4j.Logger; import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus;
public class GoodbyeTasklet implements Tasklet{
private static final Logger LOGGER = Logger.getLogger(GoodbyeTasklet.class);
@Override public RepeatStatus execute(StepContribution arg0, ChunkContext arg1) throws Exception {
LOGGER.info("Goodbye Spring Batch!");
return RepeatStatus.FINISHED; }
} |
Tasklet(Step)이 실행되었을때, 단순히 "Goodbye Spring Batch!" 메시지를 콘솔에 출력합니다.
4. JobListener 작성
package com.hjh.batch;
import org.apache.log4j.Logger; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobExecutionListener;
public class JobListener implements JobExecutionListener {
private static final Logger LOGGER = Logger.getLogger(JobListener.class);
@Override public void afterJob(JobExecution exec) { LOGGER.info(">>> Job Executed: " + exec.getJobInstance().getJobName() + " : Batch Status: " + exec.getStatus());
}
@Override public void beforeJob(JobExecution exec) { LOGGER.info(">>> Job To Be Executed: " + exec.getJobInstance().getJobName()); }
} |
Job이 실행되기 전에 beforeJob()이 호출되며, Job 실행이 종료되면 afterJob이 호출됩니다.
5. StepListener 작성
package com.hjh.batch;
import org.apache.log4j.Logger; import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.StepExecution; import org.springframework.batch.core.StepExecutionListener;
public class StepListener implements StepExecutionListener{
private static final Logger LOGGER = Logger.getLogger(StepListener.class);
@Override public ExitStatus afterStep(StepExecution exec) { LOGGER.info("### Step Executed: " + exec.getStepName());
return null; }
@Override public void beforeStep(StepExecution exec) { LOGGER.info("### Step To Be Executed: " + exec.getStepName());
}
} |
Step이 실행되기 전에 beforeStep()이 호출되며, Step 실행이 종료되면 afterStep이 호출됩니다.
6. JobRuntime 작성 (커스텀 Job Launcher)
package com.hjh.batch;
import org.apache.log4j.Logger; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.launch.JobLauncher;
public class JobRuntime {
private static final Logger LOGGER = Logger.getLogger(JobRuntime.class);
private JobLauncher jobLauncher;
private Job job;
public JobRuntime(){
}
public void setJobLauncher(JobLauncher jobLauncher){ this.jobLauncher = jobLauncher; }
public void setJob(Job job){ this.job = job; }
public void launch() throws Exception{
JobParameters jobParameters = new JobParametersBuilder().addLong("batch-date", System.currentTimeMillis()).toJobParameters();
JobExecution exec = jobLauncher.run(job, jobParameters);
LOGGER.info("Exit Status: " + exec.getStatus());
}
} |
메인 메소드에서 lauch() 메소드를 호출하면 Job 이 실행됩니다.
7. 실행
Job을 실행하는 방법에는 두가지가 있습니다.
첫번째는, 예제에서 사용된 것처럼 커스텀 런쳐를 만들어서 실행하는 방법입니다.
예제에서 다음과 같이 메인 메소드 코드를 확인하세요.
public static void main(String[] args) {
try { /** * Job 실행 방벙1 * 직접 JobLauncher를 호출하여 실형하는 방법 */
Launcher.appContext = new ClassPathXmlApplicationContext( SPRING_CONTEXT_CONFIG_FILE_PATH);
JobRuntime runtime = (JobRuntime) appContext.getBean("runtime");
runtime.launch();
} catch (Exception e) { LOGGER.info("Launcher has failed", e); System.exit(-1); } } |
두번째는, CommandLineJobRunner을 사용하는 방법입니다.
CommandLineJobRunner의 main() 메소드는 두개의 arguements를 받는데, 첫번째는 sping application context file이며, 두번째는 등록된 job이 이름을 받습니다.
CommandLineJobRunner.main(new String[]{"config/spring-context.xml", "simpleJob"}); |
8. 결과
결과에서 Job 실행 이전 이후 JobListener가 호출된 로그와, 각 Step 실행 이전 이후 StepListener가 호출된 로그를 확인해 보세요.
Job 종류 이후 Exit Status: COMPLETED가 출력된 것도 확인 하세요.
2013-07-04 22:06:02,431 INFO [com.hjh.batch.JobListener] - >>> Job To Be Executed: simpleJob (JobListener.java:19) beforeJob 2013-07-04 22:06:02,469 INFO [org.springframework.batch.core.job.SimpleStepHandler] - Executing step: [helloStep] (SimpleStepHandler.java:133) handleStep 2013-07-04 22:06:02,487 INFO [com.hjh.batch.StepListener] - ### Step To Be Executed: helloStep (StepListener.java:21) beforeStep 2013-07-04 22:06:02,542 INFO [com.hjh.batch.HelloWorldTasklet] - Spring Batch Hellow World Tasklet! (HelloWorldTasklet.java:17) execute 2013-07-04 22:06:02,568 INFO [com.hjh.batch.StepListener] - ### Step Executed: helloStep (StepListener.java:14) afterStep 2013-07-04 22:06:02,662 INFO [org.springframework.batch.core.job.SimpleStepHandler] - Executing step: [goodbyeStep] (SimpleStepHandler.java:133) handleStep 2013-07-04 22:06:02,666 INFO [com.hjh.batch.StepListener] - ### Step To Be Executed: goodbyeStep (StepListener.java:21) beforeStep 2013-07-04 22:06:02,669 INFO [com.hjh.batch.GoodbyeTasklet] - Goodbye Spring Batch! (GoodbyeTasklet.java:17) execute 2013-07-04 22:06:02,676 INFO [com.hjh.batch.StepListener] - ### Step Executed: goodbyeStep (StepListener.java:14) afterStep 2013-07-04 22:06:02,690 INFO [com.hjh.batch.JobListener] - >>> Job Executed: simpleJob : Batch Status: COMPLETED (JobListener.java:13) afterJob 2013-07-04 22:06:02,696 INFO [org.springframework.batch.core.launch.support.SimpleJobLauncher] - Job: [FlowJob: [name=simpleJob]] completed with the following parameters: [{batch-date=1372943162216}] and the following status: [COMPLETED] (SimpleJobLauncher.java:121) run 2013-07-04 22:06:02,696 INFO [com.hjh.batch.JobRuntime] - Exit Status: COMPLETED (JobRuntime.java:37) launch |
출처: http://willygwu2003.blog.me/130171511927
6. 예제3: Spring Batch - Read from flat file and write to DB (0) | 2016.03.31 |
---|---|
5. 예제2: Spring Batch Job HelloWorld - ItemReader,ItemProcessor,ItemWriter (0) | 2016.03.31 |
3. Spring Batch ItemReader, ItemProcessor, ItemWrtier (0) | 2016.03.31 |
2. Understanding Job and Step Configuration in Spring Batch (0) | 2016.03.31 |
1. Spring Batch Basics (0) | 2016.03.31 |
댓글 영역