MULTI FILE READ / WRITE
-
배치 작업 Xml Sample
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:batch-int="http://www.springframework.org/schema/batch-integration"
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
http://www.springframework.org/schema/batch-integration http://www.springframework.org/schema/batch-integration/spring-batch-integration.xsd">
<!--
* 배치작업 : MULTI FILE READ TO MULTI FILE WRITE 샘플
* 배치스텝
- sample-multifile-to-multifile-001 : Multi File(Read/Write) 처리 스텝. Java Code로 처리하는 파일 처리 예제.
-->
<job id="sample-multifile-to-multifile" xmlns="http://www.springframework.org/schema/batch">
<step id="sample-multifile-to-multifile-001">
<tasklet>
<chunk reader="SmpMultiFileToMultiFileChunk" processor="SmpMultiFileToMultiFileChunk" writer="SmpMultiFileToMultiFileChunk" />
</tasklet>
</step>
</job>
</beans>
-
배치 소스코드 Sample
package sample.batch.service;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemStream;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import bxm.common.annotaion.BxmCategory;
import bxmc.batch.ext.context.DefaultBatchApplicationContext;
import bxmc.batch.ext.utils.DefaultFileUtils;
import bxmc.batch.item.reader.ext.DelimitedFileReader;
import bxmc.batch.item.reader.ext.FixedFileReader;
import bxmc.batch.item.writer.ext.DelimitedFileWriter;
import bxmc.batch.item.writer.ext.FixedFileWriter;
import sample.batch.service.dto.SmpMultiFileToMultiFileChunkDto;
/**
* 샘플 DB TO DB 배치
*
* @author sysadmin
*/
@Scope("step")
@Service("SmpMultiFileToMultiFileChunk")
@BxmCategory(logicalName="샘플 MultiFile TO MultiFile 배치", description="샘플 MultiFile TO MultiFile 배치")
public class SmpMultiFileToMultiFileChunk implements ItemStream, ItemReader<SmpMultiFileToMultiFileChunkDto>
, ItemProcessor<SmpMultiFileToMultiFileChunkDto, SmpMultiFileToMultiFileChunkDto>, ItemWriter<SmpMultiFileToMultiFileChunkDto>{
private Logger logger= LoggerFactory.getLogger(getClass());
private FixedFileReader<SmpMultiFileToMultiFileChunkDto> empInfoFixedReader = null;
private DelimitedFileReader<SmpMultiFileToMultiFileChunkDto> empInfoDelimitedReader = null;
private FixedFileWriter<SmpMultiFileToMultiFileChunkDto> empInfoFixedWriter = null;
private DelimitedFileWriter<SmpMultiFileToMultiFileChunkDto> empInfoDelimitedWriter = null;
private int readFileCount = 0;
/**
* open
* - 초기화를 위해 구현해야 하는 Method 로서 스텝이 시작되기 전에 FW에서 최초 1번 호출된다.
*/
@Override
@BxmCategory(logicalName = "open : 샘플용 Multi File Open 처리", description = "open : 샘플용 Multi File Open 처리")
public void open(ExecutionContext executionContext) throws ItemStreamException {
// 부서번호 파라미터 확인
String deptNoStr = DefaultBatchApplicationContext.getJobParameter("deptNo");
if(deptNoStr == null) {
throw new ItemStreamException("deptNo is null or empty.");
}
int deptNo = Integer.valueOf(deptNoStr);
String prefixFilePath = System.getProperty("prefixFilePath");
/**
* 샘플용 직원1정보 Fixed File Open
*/
String empInfoFixedFileReadName = prefixFilePath + "/test-fixed-file-" + deptNo + ".txt";
empInfoFixedReader = DefaultFileUtils.getFixedFileReader(empInfoFixedFileReadName, SmpMultiFileToMultiFileChunkDto.class, "UTF-8");
empInfoFixedReader.open(executionContext); // File Open
/**
* 샘플용 직원2정보 Delimited File Open
*/
String empInfoDelimitedFileReadName = prefixFilePath + "/test-delimited-file-" + deptNo + ".txt";
empInfoDelimitedReader = DefaultFileUtils.getDelimitedFileReader(empInfoDelimitedFileReadName, SmpMultiFileToMultiFileChunkDto.class, ";", "UTF-8");
empInfoDelimitedReader.open(executionContext); // File Open
/**
* 샘플용 직원정보 Fixed File Open
*/
String empInfoFixedFileWriteName = prefixFilePath + "/test-fixed-file-mf-" + deptNo + ".txt";
empInfoFixedWriter = DefaultFileUtils.getFixedFileWriter(empInfoFixedFileWriteName, SmpMultiFileToMultiFileChunkDto.class, "UTF-8");
empInfoFixedWriter.open(executionContext); // File Open
/**
* 샘플용 직원정보 Delimited File Open
*/
String empInfoDelimitedFileName = prefixFilePath + "/test-delimited-file-mf-" + deptNo + ".txt";
empInfoDelimitedWriter = DefaultFileUtils.getDelimitedFileWriter(empInfoDelimitedFileName, SmpMultiFileToMultiFileChunkDto.class, ",", "UTF-8");
empInfoDelimitedWriter.open(executionContext); // File Open
}
/**
* read
* - 처리 대상 데이터를 건 별로 DB 또는 파일에서 읽어오는 역할을 수행한다.
*/
@Override
@BxmCategory(logicalName = "read : 샘플용 직원정보 파일 Read", description = "read : 샘플용 직원정보를 1건씩 Read한다.")
public SmpMultiFileToMultiFileChunkDto read()
throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
SmpMultiFileToMultiFileChunkDto out = null;
// 첫번째 파일 Read
if(readFileCount == 0) {
out = empInfoFixedReader.read();
if(out != null) {
return out;
}
else {
// 더이상 읽을 데이터가 없을 경우 다음 파일로 처리
readFileCount = 1;
}
}
// 두번째 파일 Read
if(readFileCount == 1) {
out = empInfoDelimitedReader.read();
if(out != null) {
return out;
}
}
return out;
}
/**
* process
* - 처리 대상 데이터를 건 별로 업무요건에 따라 처리하는 역할을 수행한다.
*/
@Override
@BxmCategory(logicalName = "process : 샘플용 직원정보 처리", description = "process : 샘플용 직원정보를 1건씩 처리한다.")
public SmpMultiFileToMultiFileChunkDto process(SmpMultiFileToMultiFileChunkDto in) throws Exception {
SmpMultiFileToMultiFileChunkDto out;
/**
* 관리자임직원번호가 없는 경우에는 null 를 return 하여 해당 Item에 대하여 Skip 처리한다.
* - 참고 : process에서 null을 return 하면 write로 item이 넘어가지 않는다.
*/
if(in.getFeduMngrEmpNo() == 0)
{
logger.warn("임직원번호[{}]에 대한 관리자 번호가 0 입니다. Skip 처리합니다.", in.getFeduEmpNo());
return null;
}
/**
* 개별 업무로직 수행
* ...
* ...
*/
out = in;
return out;
}
/**
* write
* - 처리 대상 결과 데이터를 커밋 단위 별로 DB 또는 파일에 기록처리하는 역할을 수행한다.
*/
@Override
@BxmCategory(logicalName = "샘플용 Multi File write", description = "샘플용 Multi File write")
public void write(List<? extends SmpMultiFileToMultiFileChunkDto> in) throws Exception
{
List<SmpMultiFileToMultiFileChunkDto> fixedFileDtos = new ArrayList<SmpMultiFileToMultiFileChunkDto>();
List<SmpMultiFileToMultiFileChunkDto> delimitedFileDtos = new ArrayList<SmpMultiFileToMultiFileChunkDto>();
for(SmpMultiFileToMultiFileChunkDto smpMultiFileToMultiFileChunkDto : in)
{
/**
* Fixed File 처리 Data 설정
*/
SmpMultiFileToMultiFileChunkDto fixedFileDto = new SmpMultiFileToMultiFileChunkDto();
fixedFileDto.setFeduEmpNo(smpMultiFileToMultiFileChunkDto.getFeduEmpNo()); // set [FW샘플 임직원번호]
fixedFileDto.setFeduEmpNm(smpMultiFileToMultiFileChunkDto.getFeduEmpNm()); // set [FW샘플 임직원명]
fixedFileDto.setFeduOccpNm(smpMultiFileToMultiFileChunkDto.getFeduOccpNm()); // set [FW샘플 직업명]
fixedFileDto.setFeduMngrEmpNo(smpMultiFileToMultiFileChunkDto.getFeduMngrEmpNo()); // set [FW샘플 관리자임직원번호]
fixedFileDto.setFeduHireDt(smpMultiFileToMultiFileChunkDto.getFeduHireDt()); // set [FW샘플 입사일자]
fixedFileDto.setFeduPayAmt(smpMultiFileToMultiFileChunkDto.getFeduPayAmt()); // set [FW샘플 급여금액]
fixedFileDto.setFeduDeptNo(smpMultiFileToMultiFileChunkDto.getFeduDeptNo()); // set [FW샘플 부서번호]
fixedFileDtos.add(fixedFileDto);
/**
* Delimited File 처리 Data 설정
*/
SmpMultiFileToMultiFileChunkDto delimitedFileDto = new SmpMultiFileToMultiFileChunkDto();
delimitedFileDto.setFeduEmpNo(smpMultiFileToMultiFileChunkDto.getFeduEmpNo()); // set [FW샘플 임직원번호]
delimitedFileDto.setFeduEmpNm(smpMultiFileToMultiFileChunkDto.getFeduEmpNm()); // set [FW샘플 임직원명]
delimitedFileDto.setFeduOccpNm(smpMultiFileToMultiFileChunkDto.getFeduOccpNm()); // set [FW샘플 직업명]
delimitedFileDto.setFeduMngrEmpNo(smpMultiFileToMultiFileChunkDto.getFeduMngrEmpNo()); // set [FW샘플 관리자임직원번호]
fixedFileDto.setFeduHireDt(smpMultiFileToMultiFileChunkDto.getFeduHireDt()); // set [FW샘플 입사일자]
delimitedFileDto.setFeduPayAmt(smpMultiFileToMultiFileChunkDto.getFeduPayAmt()); // set [FW샘플 급여금액]
delimitedFileDto.setFeduDeptNo(smpMultiFileToMultiFileChunkDto.getFeduDeptNo()); // set [FW샘플 부서번호]
delimitedFileDtos.add(delimitedFileDto);
}
/**
* File Write 처리
*/
empInfoFixedWriter.write(fixedFileDtos); // Fixed File Write
empInfoDelimitedWriter.write(delimitedFileDtos); // Delimited File Write
}
/**
* update
* - 진행 상태를 기록하기 위해 구현해야 하는 Method로서 구간 별로 Commit 시에 FW에서 호출된다.
*/
@Override
@BxmCategory(logicalName = "update", description = "update")
public void update(ExecutionContext executionContext) throws ItemStreamException {
if(empInfoFixedReader != null) empInfoFixedReader.update(executionContext);
if(empInfoDelimitedReader != null) empInfoDelimitedReader.update(executionContext);
if(empInfoFixedWriter != null) empInfoFixedWriter.update(executionContext);
if(empInfoDelimitedWriter != null) empInfoDelimitedWriter.update(executionContext);
}
/**
* close
* - 리소스 정리 작업을 위해 구현해야 하는 Method로서 Step 완료 시에 FW에서 호출된다.
*/
@Override
@BxmCategory(logicalName = "close", description = "close")
public void close() throws ItemStreamException {
if(empInfoFixedReader != null) empInfoFixedReader.close();
if(empInfoDelimitedReader != null) empInfoDelimitedReader.close();
if(empInfoFixedWriter != null) empInfoFixedWriter.close();
if(empInfoDelimitedWriter != null) empInfoDelimitedWriter.close();
}
}