후행 처리 커스터마이징
이번 장은 후행 처리 커스터마이징에 대하여 설명하는 장이다.
1. 후행 처리 커스터마이징 Interface
후행 처리 커스터 마이징은 아래의 3가지의 Interface를 이용하여 커스터 마이징을 할 수 있다.
Interface | 설명 |
---|---|
IDeferredApTableReader |
타겟 테이블에서 처리일련번호를 조회 처리 |
IDeferredPrePostProcessor |
후행 처리 선/후처리 |
IDeferredUtils |
영업일/업무마감여부를 처리 |
INumberingPrePostProcessor |
넘버링 선/후처리 |
2. IDeferredApTableReader Interface
타겟 테이블에서 후행 처리의 일련번호를 조회 하는 Interface 이다.
2.1. 구현 Method
IDeferredApTableReader 의 구현 Method는 다음과 같다.
public IDeferredExecInfo getApTableProcInfo(final IDeferredMainInfo deferredMainInfo, final long lastSeq);
2.1.1. getApTableProcInfo() Method
타겟 테이블에서 후행 처리가 일련번호를 조회 한다.
속성 |
설명 |
|
파라 미터 |
IDeferredMainInfo |
후행 처리 메인/상태 정보를 조회한 정보 |
long lastSeq |
후행처리작업(BXM_DEFERRED_WORK)테이블에서 마지막으로 조회한 종료일련번호 |
|
리턴 |
IDeferredExcelInfo |
후행 처리 실행(BXM_DEFERRED_EXEC)에 등록할 실행 정보 |
getApTableProcInfo() Sample
아래의 예는 타겟 테이블에서 일련번호를 조회하는 예로서, 만일 실행할 일련번호가 존재하지 않으면 null을 return 한다.
private static final String SELECT_APTABLE_SQL =
" SELECT MAX(%s) " +
" FROM %s " +
" WHERE %s > ? AND %s <= COALESCE(CAST(? as int), 0) + ? " +
" %s "
;
@Override
public IDeferredExecInfo getApTableProcInfo(final IDeferredMainInfo deferredMainInfo, long maxSeq)
{
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
IDeferredExecInfo deferredExecInfo = null;
try
{
conn = BxmDeferredUtils.getConnection();
// Table명 설정
String tableName = null;
if(deferredMainInfo.isDayTableYn())
{
tableName = new StringBuilder().append(deferredMainInfo.getTargetTableNm())
.append(DeferredConstants.TABLE_WORD_SEPARATE_VAL)
.append(BxmDeferredUtils.getDay(deferredMainInfo.getBizDt()))
.toString();
}
else
{
tableName = deferredMainInfo.getTargetTableNm();
}
String sql = null;
// 노드병 실행 여부에 따른 조회 쿼리 정의
if(deferredMainInfo.isNodeExecYn())
{
sql = String.format(SELECT_APTABLE_SQL
, deferredMainInfo.getTargetColumnNm()
, tableName
, deferredMainInfo.getTargetColumnNm()
, deferredMainInfo.getTargetColumnNm()
, DeferredConstants.WHERE_NODE_NO_SQL
);
}
else
{
sql = String.format(SELECT_APTABLE_SQL
, deferredMainInfo.getTargetColumnNm()
, tableName
, deferredMainInfo.getTargetColumnNm()
, deferredMainInfo.getTargetColumnNm()
, ""
);
}
pstmt = conn.prepareStatement(sql);
int ix = 0;
pstmt.setLong(++ix, maxSeq);
pstmt.setLong(++ix, maxSeq);
pstmt.setInt(++ix, deferredMainInfo.getFetchCnt());
if(deferredMainInfo.isNodeExecYn())
{
pstmt.setInt(++ix, BxmDeferredUtils.getNodeNo());
}
rs = pstmt.executeQuery();
if(rs.next())
{
// 실행정보 설정
long startSeq = maxSeq + 1;
long endSeq = rs.getLong(1);
if(startSeq != 0 && startSeq <= endSeq)
{
deferredExecInfo = new DeferredExecInfo();
deferredExecInfo.setStartSeq(startSeq);
deferredExecInfo.setEndSeq(endSeq);
deferredExecInfo.setDeferredId(deferredMainInfo.getDeferredId());
deferredExecInfo.setNodeNo(BxmDeferredUtils.getNodeNo());
deferredExecInfo.setBizDt(deferredMainInfo.getBizDt());
deferredExecInfo.setDeferredStatusCd(DeferredConstants.EXEC_STATUS_PROCEEDING);
deferredExecInfo.setStartDttm(BxmDeferredUtils.getCurrentSystemTime());
deferredExecInfo.setErrCd("");
deferredExecInfo.setErrMsgCtt("");
}
}
}
catch (Exception e)
{
logger.error(e.getMessage(), e);
throw new IllegalStateException(e);
}
finally
{
BxmDeferredUtils.closeDbConn(conn, pstmt, rs);
}
return deferredExecInfo;
}
참고로, 후행 처리 메인 에서 테이블리더빈 명(TABLE_READER_BEAN_NM)이 정의되어 있다면 해당 Interface는 수행하지 않는다.
3. IDeferredPrePostProcessor Interface
후행 처리 선/후처리 및 후행 처리 서비스 호출에 대하여 커스터마이징 할 수 있도록 제공하고 있는 Interface 이다.
3.1. 구현 Method
IDeferredPrePostProcessor 의 구현 Method는 다음과 같다.
public IOmmObject deferredPreProcessor(final ContextHeader cHeader, final Application application
, final ServiceTraceContextImpl serviceTraceContextImpl, final IDeferredMainInfo deferredMainInfo
, final IDeferredExecInfo deferredExecInfo, final Long procSeq);
public void executeDeferredService(final ContextHeader cHeader,
final ServiceTraceContextImpl serviceTraceContextImpl,
final IDeferredMainInfo deferredMainInfo, final IOmmObject iOmmObject) throws NestedRuntimeException, NestedCheckedException;
public void deferredErrorPostProcessor(final ContextHeader cHeader
, final IDeferredMainInfo deferredMainInfo, final IDeferredExecInfo deferredExecInfo, Exception exception, long procNum);
public void deferredPostProcessor(final ContextHeader cHeader, final IDeferredMainInfo deferredMainInfo
, final IDeferredExecInfo deferredExecInfo);
3.1.1. deferredPreProcessor() Method
후행 처리 서비스를 호출하기 위한 선처리 작업을 수행하는 Method 이다. 해당 Method 에서는 헤더, 후행 처리 전달 OMM 등을 정의 할 수 있다.
속성 |
설명 |
|
파라 미터 |
ContextHeader cHeader |
시스템 헤더 |
Application application |
Deploy한 Application |
|
ServiceTraceContextImpl serviceTraceContextImpl |
서비스 Trace Context |
|
IDeferredMainInfo deferredMainInfo |
후행 처리 메인/상태 정보를 조회한 정보 |
|
Long procSeq |
현재 처리 일련번호 |
|
리턴 |
IOmmObject |
후행 처리 서비스에 전달할 OMM(Default OMM은 DeferredExcelO) |
deferredPreProcessor() Sample
아래의 예는 후행 처리 선 처리에서 구현하는 예시이다. 필요 시 해당 선 처리에서 로그레벨, 후행 처리 서비스 입력 OMM 등 다양하게 프로젝트 환경에 맞춰 커스터마이징을 할 수 있다.
@Override
public DeferredExecIO deferredPreProcessor(final ContextHeader cHeader, final Application application,
final ServiceTraceContextImpl serviceTraceContextImpl, final IDeferredMainInfo deferredMainInfo
, final IDeferredExecInfo deferredExecInfo, final Long procSeq)
{
// Header 설정
cHeader.setRemoteAddr("localhost");
cHeader.setUuid(SystemUtils.generateGUID());
((IOmmObject)cHeader).set("userId", "deferredExecutor");
// 후행 처리 Service 입력 데이터 생성
DeferredExecIO deferredExecIO = new DeferredExecIO();
deferredExecIO.setDeferredId(deferredExecInfo.getDeferredId());
deferredExecIO.setBizDt(deferredExecInfo.getBizDt());
// 일련번호 하나씩.. 서비스 호출
if(DeferredConstants.SVC_PROC_ONE.equals(deferredMainInfo.getSvcProcCd()))
{
// Error 가 발생한 일련번호 설정
deferredExecIO.setProcSeq(procSeq);
}
// 대상전체.. 서비스 호출
else if(DeferredConstants.SVC_PROC_ALL.equals(deferredMainInfo.getSvcProcCd()))
{
deferredExecIO.setStartSeq(deferredExecInfo.getStartSeq());
deferredExecIO.setEndSeq(deferredExecInfo.getEndSeq());
}
deferredExecIO.setTargetTableNm(deferredMainInfo.getTargetTableNm());
deferredExecIO.setTargetColumnNm(deferredMainInfo.getTargetColumnNm());
deferredExecIO.setNodeNo(deferredExecInfo.getNodeNo());
return deferredExecIO;
}
3.1.2. executeDeferredService() Method
후행 처리 서비스를 호출하기 위한 Method이다.
속성 |
설명 |
|
파라 미터 |
ContextHeader cHeader |
시스템 헤더 |
ServiceTraceContextImpl serviceTraceContextImpl |
서비스 Trace Context |
|
IDeferredMainInfo deferredMainInfo |
후행 처리 메인/상태 정보를 조회한 정보 |
|
IOmmObject iOmmObject |
후행 처리 서비스의 입력 DTO |
|
리턴 |
void |
executeDeferredService() Sample
아래의 예는 후행 처리 서비스를 호출 하는 예이다.
@Override
public void executeDeferredService(final ContextHeader cHeader,
final ServiceTraceContextImpl serviceTraceContextImpl, final IDeferredMainInfo deferredMainInfo, final IOmmObject iOmmObject)
throws NestedRuntimeException, NestedCheckedException
{
// Deferred Service 호출
ServiceExecutor.execute(deferredMainInfo.getBxmAppId(), deferredMainInfo.getSvcNm()
, deferredMainInfo.getOpNm(), iOmmObject);
}
3.1.3. deferredPostProcessor() Method
후행 처리 서비스가 정상적으로 처리가 완료가 된 경우에 호출 되는 Method 이다. 서비스 처리 완료 후에 추가적으로 처리할 부분이 있으면 해당 Method 에서 커스터마이징을 할 수 있다.
속성 |
설명 |
|
파라 미터 |
ContextHeader cHeader |
시스템 헤더 |
ServiceTraceContextImpl serviceTraceContextImpl |
서비스 Trace Context |
|
IDeferredMainInfo deferredMainInfo |
후행 처리 메인/상태 정보를 조회한 정보 |
|
IDeferredExecInfo deferredExecInfo |
후행 처리 서비스 실행 정보 |
|
리턴 |
void |
deferredPostProcessor()
아래는 후행 처리 후처리 Sample Method이다.
@Override
public void deferredPostProcessor(final ContextHeader cHeader, final IDeferredMainInfo deferredMainInfo, final IDeferredExecInfo deferredExecInfo)
{
}
3.1.4. deferredErrorPostProcessor() Method
후행 처리 서비스에서 에러가 발생한 경우에 호출 되는 Method 이다. 에러 발생 시 추가적으로 처리할 부분이 있으면 해당 Method 에서 커스터마이징을 할 수 있다.
속성 |
설명 |
|
파라 미터 |
ContextHeader cHeader |
시스템 헤더 |
IDeferredMainInfo deferredMainInfo |
후행 처리 메인/상태 정보를 조회한 정보 |
|
IDeferredExecInfo deferredExecInfo |
후행 처리 서비스 실행 정보 |
|
Exception exception |
후행 처리 서비스에서 발생한 Exception 정보 |
|
int procNum |
현재처리일련번호 |
|
리턴 |
void |
deferredErrorPostProcessor()
아래는 후행 처리 에러 후처리 Sample Method 이다.
@Override
public void deferredErrorPostProcessor(final ContextHeader cHeader
, final IDeferredMainInfo deferredMainInfo, final IDeferredExecInfo deferredExecInfo, Exception exception, int procNum)
{
}
4. IDeferredUtils Interface
후행 처리 수행 시 영업일자와 업무마감여부를 확인하기 위한 Interface 이다.
4.1. 구현 Method
IDeferredUtils 의 구현 Method는 다음과 같다.
public String loadBizDt();
public boolean isApEndYn(IDeferredMainInfo deferredMainInfo);
public void decideApEndYn(IDeferredMainInfo deferredMainInfo, IDeferredWorkInfo deferredWorkInfo);
4.2. isApEndYn() Method
업무마감 여부를 판단하는 Method 이다.
속성 | 설명 | |
---|---|---|
파라 미터 |
IDeferredMainInfo deferredMainInfo |
후행 처리 메인/상태 정보 |
리턴 |
boolean |
마감여부 |
isApEndYn() Sample
아래의 예는 업무마감여부를 판단하는 예이다. Default는 후행 처리의 영업일자와 System 일자가 다를 경우 마감으로 판단하고 true로 return 한다.
사이트에 맞게 커스텀마이징 해야 한다.
@Override
public boolean isApEndYn(IDeferredMainInfo deferredMainInfo) {
// 업무에대한 마감 여부를 판단한다.
// 현재는 입력받은 영업일자와 현재의 System 일자를 비교하여 다르면 마감이라고 판단한다.
// 마감여부 판단은 시스템에 따라서 처리하는 부분이 다르기 때문에.. 필요시 해당 Method에서 구현하여 처리할 수 있도록 한다.
String sysDt = DateUtils.getCurrentDate(DateUtils.EMPTY_DATE_TYPE);
return sysDt.equals(deferredMainInfo.getBizDt()) ? false : true;
}
4.2.1. decideApEndYn() Method
업무마감을 결정하는 Method이다.
속성 | 설명 | |
---|---|---|
파라 미터 |
IDeferredMainInfo deferredMainInfo ,IDeferredWorkInfo |
후행 처리 메인/상태 정보 |
리턴 |
void |
없음 |
decideApEndYn() Sample
아래의 예는 업무마감을 결정하는 예이다.
@Override
public void decideApEndYn(IDeferredMainInfo deferredMainInfo, IDeferredWorkInfo deferredWorkInfo)
{
if ( !isApEndYn(deferredMainInfo))
{
return ;
}
if (isExistingRunningDeferredService(deferredMainInfo))
{
logger.info("Deferred[{}] is running. Can not be closed.", deferredMainInfo.getDeferredId());
}
else
{
if (isEndDeferredProcessor(deferredMainInfo))
{
workEnd(deferredMainInfo, deferredWorkInfo);
}
}
}
private boolean isExistingRunningDeferredService(IDeferredMainInfo deferredMainInfo)
{
return (DeferredContainer.getDeferredDBProcessor().getDeferredExecInfoCount(deferredMainInfo) > 0);
}
private void workEnd(IDeferredMainInfo deferredMainInfo, IDeferredWorkInfo deferredWorkInfo)
{
deferredWorkInfo.setEndYn(true);
int result = DeferredContainer.getDeferredDBProcessor().modifyDeferredWorkEnd(deferredWorkInfo);
if(result != 0)
{
logger.info("Deferred[{}] to NodeNo[{}]/BizDate[{}] is now complete."
, new Object[]{deferredMainInfo.getDeferredId()
, deferredWorkInfo.getNodeNo()
, deferredMainInfo.getBizDt()});
}
}
5. INumberingPrePostProcessor Interface
넘버링 선/후 처리를 할 수 있도록 제공하는 Interface이다.
5.1. 구현 Method
INumberingPrePostProcessor 의 구현 Method는 다음과 같다.
public void numberingPreProcessor(final ContextHeader cHeader, final IDeferredMainInfo deferredMainInfo);
public void numberingPostProcessor(final ContextHeader cHeader, final IDeferredMainInfo deferredMainInfo);
public void numberingErrorPostProcessor(final ContextHeader cHeader, final IDeferredMainInfo deferredMainInfo, Exception exception);
5.1.1. numberingPreProcessor() Method
넘버링 선처리 Method이다.
속성 |
설명 |
|
파라 미터 |
ContextHeader cHeader |
시스템 헤더 |
IDeferredMainInfo deferredMainInfo |
후행 처리 메인/상태 정보 |
|
리턴 |
void |