2018. 9. 27. 23:16ㆍSpring Batch
HelloJob.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd"> <job id="HelloJob" xmlns="http://www.springframework.org/schema/batch"> <step id="HelloStep"> <tasklet> <chunk reader="HelloReader" processor="HelloProcessor" writer="HelloWriter" commit-interval="10"/> </tasklet> </step> </job> <!-- Reader Bean Injection --> <bean id="HelloReader" class="com.batchguide.hello.HelloReader" scope="step"> <property name="bseYm" value="#{jobParameters['BSEYM']}" /> </bean> <!-- Processor Bean Injection --> <bean id="HelloProcessor" class="com.batchguide.hello.HelloProcessor" /> <!-- Writer Bean Injection --> <bean id="HelloWriter" class="com.batchguide.hello.HelloWriter" /> </beans>
CommonUtils.java
package com.batchguide.util; import java.util.ArrayList; import java.util.List; public class CommonUtils { /** * 입력 파라미터 정보 추출 * * @param params 입력파라미터 * @return 입력파라미터 정보 */ public static ArrayList<String> makeParameters(List<String> params) { ArrayList<String> retList = new ArrayList<String>(); /* * 입력파라미터는 key=value 형태로 이루어지므로 입력 스트림에 대한 필터 처리 후 * 파라미터 정보만 리스트에 담는다. */ params.stream().filter(p -> p.contains("=")).forEach(param -> { retList.add(param.split("=")[0].toUpperCase() + "=" + param.split("=")[1]); }); return retList; } }
프로그램 실행시 파라미터정보는 key=value 형태로 입력이 되어지는데 입력파라미터만 별도로 추출 하는 함수
RunBatch.java
package com.batchguide.util; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.concurrent.atomic.AtomicInteger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import egovframework.rte.bat.core.launch.support.EgovCommandLineRunner; public class RunBatch { private static final Logger LOGGER = LoggerFactory.getLogger(RunBatch.class); public static void start(String...args) { EgovCommandLineRunner command = new EgovCommandLineRunner(); HashSet<String> opts = new HashSet<String>(); // JOB_PATH 설정 String jobPath = args[0]; // JOB_ID 설정 String jobId = args[1]; ArrayList newList = new ArrayList(Arrays.asList(args)); newList.add("TIMESTAMP=" + (new Date()).getTime()); ArrayList<String> paramList = CommonUtils.makeParameters(newList); // 입력파라마터출력 AtomicInteger atomicInteger = new AtomicInteger(0); paramList.forEach(p -> System.out.println("Parameter[" + atomicInteger.getAndIncrement() +"] : " + p)); // 리스트 형태의 파라미터를 배열로 변환 String[] paramArr = paramList.stream().toArray(n -> new String[n]); // 배치프로그램실행 int statusCode = command.start(jobPath, jobId, paramArr, opts); // 배치실행결과출력 LOGGER.info("Status Code: " + statusCode); if (statusCode == 0) { System.out.println(jobId + " 성공 [SUCCESS]"); } else { LOGGER.error(jobId + " 실패 [FAIL]"); LOGGER.error("Error Message: " + EgovCommandLineRunner.getErrorMessage()); } } }
EgovCommandLineRunner.start 실행 메소드 아래와 같이 4개의 파라미터를 가진다.
/** * Batch Job을 실행한다. * 실행을 위해서 , Job 이름 / JobExecutionID, Job Parameter * 그리고 CommandLineRunner Option가 지정되어야 한다. * * @param jobPath : Job Context가 저장된 XML 파일 경로 * @param jobIdentifier : Job 이름 /JobExecutionID * @param parameters : Job Parameter * @param opts : CommandLineRunner 옵션(-restart, -next, -stop, -abandon) */ public int start(String jobPath, String jobIdentifier, String[] parameters, Set<String> opts) { ... }
jobPath : /config/batch/context-base.xml 경로
jobIdentifier(jobId) : HelloJob.xml 에 선언된 job id = "HelloJob"
parameters : key=value구조로 이루어진 배열 입력파라미터
opts : CommandLneRunner 옵션
HelloReader.java
package com.batchguide.hello; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.batch.item.ItemReader; import org.springframework.beans.factory.annotation.Value; public class HelloReader implements ItemReader<String> { private static final Logger LOGGER = LoggerFactory.getLogger(HelloReader.class); @Value("#{jobParameters['bseYm']}") public String bseYm; private String[] names = { "이철수", "김길동", "김영희" }; private int count = 0; @Override public String read() throws Exception { LOGGER.info("JOB PARAMETER VALUE : " + bseYm); if (count < names.length) { return names[count++]; } else { count = 0; } return null; } /** * @param bseYm the bseYm to set */ public void setBseYm(String bseYm) { this.bseYm = bseYm; } }
프로그램 실행 시 입력 받은 파라미터 정보를 설정하기 위해서 @Value("#jobParameters['Key name'] 설정 후 setter method 생성을 통해서 파라미터 값 설정
HelloProcessor.java
package com.batchguide.hello; import org.springframework.batch.item.ItemProcessor; public class HelloProcessor implements ItemProcessor<String, String> { @Override public String process(String name) throws Exception { return name + "!!"; } }
특별한 로직은 없는 경우는 Processor 구현은 Skip 가능
HelloWriter.java
package com.batchguide.hello; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.batch.item.ItemWriter; public class HelloWriter implements ItemWriter<String> { private static final Logger LOGGER = LoggerFactory.getLogger(HelloWriter.class); @Override public void write(List<? extends String> names) throws Exception { for (String name : names) { LOGGER.info("안녕 " + name); } } }
프로그램실행
1. 메인프로그램등록
2. Arguments 설정
3. 프로그램실행결과
실행결과에 프로그램 실행 시 설정한 파라미터 정보도 잘 나오는지 확인하기 위해 출력해보았다.
입력한 값이 정상적으로 출력되는걸 확인 할 수 있다.
다시한번 프로그램을 실행해 보자.
오류가 발생하였다.
오류메세지 "A job instance already exists and is complete for parameters={BSEYM=201810}"
오류 메세지가 발생한 원인은 jobInstance=Job+JobParameter 인데 동일한 파라미터로 두번 이상 실행하는 경우 동일 Job으로 인식하기 때문에 발생하는 오류이다. 오류해결을 위해서 RunBatch.java 25 Line 아래에 파라미터 정보를 설정해 준다.
newList.add("TIMESTAMP=" + (new Date()).getTime());
프로그램 재실행시 아래와 같이 정상적으로 수행되는 것을 확인 할 수 있을 것이다.
프로그램은 간단 하지만 Hello Friends 프로그램 작성 보다는 환경 설정 부분이 시간이 많이 걸리는 것을 알 수 있을 것이다. 하지만 다른 언어도 마찬가지 겠지만 Hello World를 만든다는 것은 단순히 System.out.println("Hello World")를 출력하기 위함이 아니라 프레임웍 및 구조에 대해 자세히 알아 가는 과정이라는 생각이 든다.
[소스레파지토리]
☞ https://github.com/roopy1210/springbatch/blob/master/spring_batch_tutorial
'Spring Batch' 카테고리의 다른 글
Spring+myBatis 환경설정 (0) | 2018.10.13 |
---|---|
Hello Friends 예제 - 2 (0) | 2018.09.29 |
스프링 배치 환경 설정하기 (0) | 2018.09.19 |
개발 환경 설정 (0) | 2018.09.17 |
스프링배치 아키텍처 및 전자정부배치프레임워크 아키텍처에 대하여. (0) | 2018.09.16 |