[Spring Batch]Transaction 롤백시 FlatFileItemWriter로 생성한 File도 롤백된다.
Computer Language/Java 2012/01/04 20:55
개발한 Batch를 Unit Test하는데, FlatFileItemWriter로 생성한 파일에 "데이터가 기록되지 않는 현상"이 발생했다.
무엇이 잘못됐는지 한참을 해맸는데.
조사해보니, Unit Test에 @Transaction 어노테이션을 붙일 경우 테스트 종료와 함께 롤백이 되는데,
FlatFileItemWriter는 Transaction이 롤백될 때 같이 롤백되도록 구현되어있었다.
Spring Batch 2.1.0.M3 부터 선택적으로 Transaction을 태울지 여부를 결정할 수 있게됐다.
- https://jira.springsource.org/browse/BATCH-1449
flatFileItemWriter의 transactional 속성은 true가 default값인데, false로 변경해주면 롤백되지 않는다.
FlatFileItemWriter를 좀 더 알아보자.
아래와 같이 기록할 file명을 넘겨주고 open을 하면 file을 기록할 준비를 하는데 FlatFileItemWriter는 facade일 뿐, 실제 파일을 기록하는 클래스를 따로 가지고있다.
transactional 속성이 true일 경우 BufferedWriter 대신에 TransactionAwareBufferedWriter를 생성한 후 File 연산과 관련한 모든것을 위임한다.
이제 TransactionAwareBufferedWriter에 대해 알아야되는데
얘는 Transaction 범위가 아닐 경우 File에 데이터를 기록하고
Transaction 범위일 경우에는 TransactionSynchronizationManager에 StringBuffer를 만들어두고 여기에 기록을 한다.
close 명령이 내려올 경우, Transaction 범위이면 TransactionSynchronizationManager에 close했다는 hint만을 남기고
Transaction 범위가 아닐경우 그냥 File을 close해버린다.
Transaction이 커밋되었을 경우에만 Buffer에 있는 내용을 꺼내 파일에 기록한다.
무엇이 잘못됐는지 한참을 해맸는데.
조사해보니, Unit Test에 @Transaction 어노테이션을 붙일 경우 테스트 종료와 함께 롤백이 되는데,
FlatFileItemWriter는 Transaction이 롤백될 때 같이 롤백되도록 구현되어있었다.
Spring Batch 2.1.0.M3 부터 선택적으로 Transaction을 태울지 여부를 결정할 수 있게됐다.
- https://jira.springsource.org/browse/BATCH-1449
flatFileItemWriter의 transactional 속성은 true가 default값인데, false로 변경해주면 롤백되지 않는다.
flatFileItemWriter.setTransactional(false);
FlatFileItemWriter를 좀 더 알아보자.
아래와 같이 기록할 file명을 넘겨주고 open을 하면 file을 기록할 준비를 하는데 FlatFileItemWriter는 facade일 뿐, 실제 파일을 기록하는 클래스를 따로 가지고있다.
flatFileItemWriter.setResource(new FileSystemResource(TEST_FILE_DIRECTORY + "/test.txt")));
flatFileItemWriter.open(executionContext);
transactional 속성이 true일 경우 BufferedWriter 대신에 TransactionAwareBufferedWriter를 생성한 후 File 연산과 관련한 모든것을 위임한다.
if (transactional) {
return new TransactionAwareBufferedWriter(writer, new Runnable() {
....
});
}
else {
return new BufferedWriter(writer);
}
이제 TransactionAwareBufferedWriter에 대해 알아야되는데
얘는 Transaction 범위가 아닐 경우 File에 데이터를 기록하고
if (!transactionActive()) {
writer.write(cbuf, off, len);
return;
}
Transaction 범위일 경우에는 TransactionSynchronizationManager에 StringBuffer를 만들어두고 여기에 기록을 한다.
// 최초 실행 시 버퍼를 초기화하고
TransactionSynchronizationManager.bindResource(bufferKey, new StringBuffer());
// 이후 수행시 꺼내서 기록
StringBuffer buffer = (StringBuffer) TransactionSynchronizationManager.getResource(bufferKey);
buffer.append(cbuf, off, len);
close 명령이 내려올 경우, Transaction 범위이면 TransactionSynchronizationManager에 close했다는 hint만을 남기고
if (transactionActive()) {TransactionSynchronizationManager.bindResource(closeKey, Boolean.TRUE);return;}
Transaction 범위가 아닐경우 그냥 File을 close해버린다.
writer.close();Transaction이 커밋되었을 경우에만 Buffer에 있는 내용을 꺼내 파일에 기록한다.
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {@Overridepublic void afterCompletion(int status) { if (status == STATUS_COMMITTED) { complete(); }
}
private void complete() {
StringBuffer buffer = (StringBuffer) TransactionSynchronizationManager.getResource(bufferKey);
if (buffer != null) {
try {
writer.write(buffer.toString());
writer.flush();
if (TransactionSynchronizationManager.hasResource(closeKey)) {
writer.close();
closeCallback.run();
}
} catch (IOException e) {
throw new FlushFailedException("Could not write to output buffer",e);
} finally {
TransactionSynchronizationManager.unbindResource(bufferKey);
if (TransactionSynchronizationManager.hasResource(closeKey)) {
TransactionSynchronizationManager.unbindResource(closeKey);
} } } } }); }
'Computer Language > Java' 카테고리의 다른 글
| [Spring Batch]Transaction 롤백시 FlatFileItemWriter로 생성한 File도 롤백된다. (0) | 2012/01/04 |
|---|---|
| [Spring] CommonsMultiPartResolver를 사용해 파일을 업로드할경우 임시파일이 쌓이는지 여부 (0) | 2011/12/15 |
| [Hudson 1.371] CPD 플러그인 설치시 Google Collections의 ImmutableList.copyOf 메소드를 찾을 수 없다는 오류 (0) | 2011/12/11 |
| [Maven] 환경변수 property를 읽지 못할 때 (0) | 2011/12/11 |
| [Maven Surefire Plugin] JUnit Test를 찾지 못할 때 (0) | 2011/12/11 |
| [Eclipse] "M2E plugin execution not covered" 오류 (0) | 2011/12/11 |


