정상 응답 MSG 코드/메시지를 레이아웃 기본값 대신 명시적으로 설정
outp_msg_cd(NCMM00001) / outp_msg_ctnt(정상처리되었습니다.) 가 표준전문 레이아웃의 기본값으로 붙어 있어서, "아무도 채우지 않은 상태" 와 "정상이라고 판정한 상태" 가 값만으로 구분되지 않았다. 2026-09 사고에서 MSG 부 파싱이 통째로 스킵됐는데도 오류가 "정상처리되었습니다." 로 보고된 것이 이 때문이다. 레이아웃 기본값을 없애고, StandardMessageCoordinatorDJB.coordinateBeforeResponse 에서 정상 응답일 때만 채운다. 이 메서드는 모든 동기 응답이 거치는 마지막 관문이라 (RequestProcessor 에서 호출) 경로를 빠짐없이 덮는다. 두 조건을 함께 본다. - 정상 응답(procs_rslt_dvcd=S) 일 때만. 오류 응답에 정상 메시지를 채우면 사고 재현이다. - 값이 비어 있을 때만(setIfBlank). 대외계가 표준응답으로 보낸 MSG 가 우선이며 덮어쓰면 JsonReader 의 MSG 부 보존 수정이 무의미해진다. 테스트: 기존 3건이 coordinateAfterRecvNonStdSyncResponse 직후에 단정하고 있었으나 값은 이제 마지막 관문에서 채워지므로, 실제 흐름대로 coordinateBeforeResponse 까지 거치도록 고치고 단정도 "공백 아님" 에서 상수 일치로 강화했다. 설계 조건을 지키는 회귀 테스트 2건을 추가했다. - 오류응답에는_정상메시지가_채워지지_않는다 - 대외계가_보낸_MSG_값은_덮어쓰지_않는다 주의: 이 CSV 는 layout.file.type=CSV 인 테스트 설정에서만 쓰인다. 운영은 DB 레이아웃을 읽으므로 DB 의 두 항목 기본값도 함께 비워야 실제 효과가 있다. 비우기 전까지는 setIfBlank 가 아무것도 하지 않아 기존과 동일하게 동작한다. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UnybKuxcuPafGhVGh4wqkZ
This commit is contained in:
@@ -77,7 +77,15 @@ public class StandardMessageCoordinatorDJB extends DefaultStandardMessageCoordin
|
||||
|
||||
// DATA 영역 경로
|
||||
public static final String DATA_SCOP_LEN = "DATA.data_scop_len";
|
||||
|
||||
|
||||
// 정상 응답 메시지.
|
||||
// 예전에는 표준전문 레이아웃의 기본값으로 붙였으나, 그렇게 두면 "아무도 채우지 않은 상태" 와
|
||||
// "정상이라고 판정한 상태" 가 구분되지 않는다. 실제로 2026-09 사고에서 MSG 부 파싱이 통째로
|
||||
// 스킵됐는데도 오류가 "정상처리되었습니다." 로 보고됐다.
|
||||
// 이제 레이아웃 기본값을 없애고, 정상이라고 판정한 지점에서만 명시적으로 설정한다.
|
||||
public static final String NORMAL_OUTP_MSG_CD = "NCMM00001";
|
||||
public static final String NORMAL_OUTP_MSG_CTNT = "정상처리되었습니다.";
|
||||
|
||||
private String[] netInfo;
|
||||
|
||||
@Override
|
||||
@@ -156,7 +164,21 @@ public class StandardMessageCoordinatorDJB extends DefaultStandardMessageCoordin
|
||||
standardMessage.setData(HEAD_MESG_RSPN_DT, now.format(FMT_DATE));
|
||||
standardMessage.setData(HEAD_MESG_RSPN_TIME, now.format(FMT_TIME_MILLIS));
|
||||
|
||||
|
||||
// 정상 응답의 MSG 코드/메시지를 여기서 채운다. 레이아웃 기본값을 없앴으므로
|
||||
// 이 지점이 정상 응답 메시지의 유일한 출처다.
|
||||
// coordinateBeforeResponse 는 모든 동기 응답이 거치는 마지막 관문이라
|
||||
// (RequestProcessor 에서 호출) 경로를 빠짐없이 덮는다.
|
||||
//
|
||||
// 반드시 두 조건을 함께 본다.
|
||||
// 1) 정상 응답일 때만. 오류 응답에 "정상처리되었습니다." 를 채우면 2026-09 사고
|
||||
// (MSG 부가 버려졌는데 오류가 정상으로 보고됨)를 코드로 재현하는 셈이다.
|
||||
// 2) 값이 비어 있을 때만. 대외계가 표준응답으로 MSG 를 채워 보낸 경우 그 값이
|
||||
// 우선이며 덮어쓰면 안 된다.
|
||||
if (STDMessageKeys.RESPONSE_TYPE_CODE_N.equals(mapper.getResponseType(standardMessage))) {
|
||||
setIfBlank(standardMessage, MSG_OUTP_MSG_CD, NORMAL_OUTP_MSG_CD);
|
||||
setIfBlank(standardMessage, MSG_OUTP_MSG_CTNT, NORMAL_OUTP_MSG_CTNT);
|
||||
}
|
||||
|
||||
StandardItem msgListRowCnt = standardMessage.findItem(StandardMessageCoordinatorDJB.MSG_LIST_ROWCNT);
|
||||
if (msgListRowCnt == null || "0".equals(msgListRowCnt.getValue()) || "".equals(msgListRowCnt.getValue())) {
|
||||
StandardItem msgPart = standardMessage.findItem("MSG");
|
||||
@@ -249,8 +271,9 @@ public class StandardMessageCoordinatorDJB extends DefaultStandardMessageCoordin
|
||||
mainMsgItem.setSize(1);
|
||||
}
|
||||
|
||||
// msg_dvcd=NM, outp_atrb_cd=0, outp_msg_cd, outp_msg_ctnt, msg_list_rowcnt=0
|
||||
// → 모두 CSV 기본값 사용
|
||||
// msg_dvcd=NM, outp_atrb_cd=0, msg_list_rowcnt=0 → 레이아웃 기본값 사용
|
||||
// outp_msg_cd, outp_msg_ctnt → 레이아웃 기본값을 없앴으므로 여기서는 비워 두고,
|
||||
// 모든 동기 응답이 거치는 coordinateBeforeResponse 에서 정상 응답일 때만 채운다.
|
||||
|
||||
makeMsgScopLen(responseMessage);
|
||||
}
|
||||
@@ -270,6 +293,17 @@ public class StandardMessageCoordinatorDJB extends DefaultStandardMessageCoordin
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 항목이 존재하고 값이 비어 있을 때만 설정한다.
|
||||
* 이미 채워진 값(대외계가 보낸 MSG, 오류 경로가 설정한 값 등)은 그대로 보존한다.
|
||||
*/
|
||||
private void setIfBlank(StandardMessage standardMessage, String path, String value) {
|
||||
StandardItem item = standardMessage.findItem(path);
|
||||
if (item != null && StringUtils.isBlank(item.getValue())) {
|
||||
item.setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveCallPropRefValues(StandardMessage standardMessage, Properties prop) {
|
||||
if (prop == null) return;
|
||||
resolveCallPropInChilds(standardMessage.getChilds(), prop);
|
||||
|
||||
Reference in New Issue
Block a user