feat: DJBank 차세대 표준전문(R10) 초기 구현

- standard-layout-djb.csv: HEAD(평면구조)/EZDATA/MSG/DATA/전문종료부(@JJ) 레이아웃 정의
- standard-message-mapping-config-djb.properties: 논리키 → 필드경로 매핑 (GUID 40자, guid_prgs_no 별도 필드 등)
- standard-message-config.properties: DJB 클래스로 전환 (CSV 방식)
- GUIDGeneratorDJB: 40자 GUID 생성 (일자+시간+밀리초+시스템코드+노드+세션+Random)
- InterfaceMapperDJB: GUID 40자, guid_prgs_no 독립 필드, 응답코드 S/F 변환
- StandardMessageCoordinatorDJB: 전문 생성/응답/에러 각 단계 후처리
- 단위테스트 45개 전체 통과 (GUIDGenerator/InterfaceMapper/Layout 검증)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
curry772
2026-04-20 11:46:18 +09:00
parent 51724ab0f5
commit 18b3e781b1
9 changed files with 1252 additions and 4 deletions
@@ -0,0 +1,92 @@
package com.eactive.eai.custom.message;
import java.security.SecureRandom;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.atomic.AtomicInteger;
/**
* DJBank(제주은행) 차세대 표준전문 GUID 생성기
*
* GUID 구성 (40자):
* 일자(8) + 시간(6) + 밀리초(3) + 시스템코드(3) + 노드번호(2) + 세션ID(12) + Random(6)
* = 8 + 6 + 3 + 3 + 2 + 12 + 6 = 40자
*/
public final class GUIDGeneratorDJB {
public static final int GUID_LENGTH = 40;
private static final DateTimeFormatter FMT_DATE = DateTimeFormatter.ofPattern("yyyyMMdd");
private static final DateTimeFormatter FMT_TIME = DateTimeFormatter.ofPattern("HHmmss");
private static final DateTimeFormatter FMT_MILLIS = DateTimeFormatter.ofPattern("SSS");
private static final AtomicInteger seq = new AtomicInteger(1);
private static final SecureRandom rnd = new SecureRandom();
private static final String NODE_NO;
private static final String SESSION_ID_BASE;
static {
// 노드번호(2): 서버명 마지막 2자리, 없으면 "00"
String serverName = System.getProperty("server.key", "");
if (serverName.length() >= 2) {
NODE_NO = serverName.substring(serverName.length() - 2);
} else {
NODE_NO = "00";
}
// 세션ID 기반(12): 호스트명 앞 12자 (부족 시 '_'로 우측패딩)
String hostname;
try {
hostname = java.net.InetAddress.getLocalHost().getHostName();
} catch (Exception e) {
hostname = "____________";
}
if (hostname.length() >= 12) {
SESSION_ID_BASE = hostname.substring(0, 12).toUpperCase();
} else {
SESSION_ID_BASE = String.format("%-12s", hostname).toUpperCase().replace(' ', '_');
}
}
private GUIDGeneratorDJB() {
}
/**
* @param systemCode 시스템구분코드 3자 (예: "EAI", "OPA")
*/
public static String getGUID(String systemCode) {
LocalDateTime now = LocalDateTime.now();
String date = now.format(FMT_DATE); // 8자
String time = now.format(FMT_TIME); // 6자
String millis = now.format(FMT_MILLIS); // 3자
// 시스템코드 3자 정규화
String sysCode = normalizeCode(systemCode, 3);
// 노드번호 2자
String nodeNo = NODE_NO;
// 세션ID 12자
String sessionId = SESSION_ID_BASE;
// Random 6자 (숫자)
int seqVal = seq.getAndUpdate(v -> v >= 999999 ? 1 : v + 1);
String random = String.format("%06d", seqVal);
String guid = date + time + millis + sysCode + nodeNo + sessionId + random;
if (guid.length() != GUID_LENGTH) {
throw new IllegalStateException("GUID length error: " + guid.length() + " [" + guid + "]");
}
return guid;
}
private static String normalizeCode(String code, int len) {
if (code == null) code = "";
code = code.toUpperCase();
if (code.length() >= len) return code.substring(0, len);
return String.format("%-" + len + "s", code).replace(' ', '_');
}
}
@@ -0,0 +1,222 @@
package com.eactive.eai.custom.message;
import org.apache.commons.lang3.StringUtils;
import com.eactive.eai.common.server.EAIServerManager;
import com.eactive.eai.message.StandardMessage;
import com.eactive.eai.message.service.DefaultInterfaceMapper;
import com.ext.eai.common.stdmessage.STDMessageKeys;
/**
* DJBank(제주은행) 차세대 표준전문 InterfaceMapper
*
* HEAD 영역이 평면 구조로 변경됨에 따라 필드 접근 경로 및 값 변환 로직을 재정의.
*
* 주요 변경사항:
* - GUID: 40자 (기존 36자)
* - GUID 진행번호: HEAD.guid_prgs_no 별도 필드 (기존 GUID 문자열 내 포함)
* - 처리결과구분코드: S(성공)/F(오류) (기존 NR/ER)
* - 시스템환경구분코드: D/T/P (기존 O/S/D)
*/
@SuppressWarnings("serial")
public class InterfaceMapperDJB extends DefaultInterfaceMapper {
private static final String PATH_MCI_NODE = "HEAD.mci_node_dvcd";
private static final String PATH_EAI_NODE = "HEAD.eai_node_dvcd";
private static final String PATH_MCI_SESN = "HEAD.mci_sesn_id";
// 처리결과구분코드 DJBank 값
private static final String PROCS_RSLT_SUCCESS = "S";
private static final String PROCS_RSLT_FAIL = "F";
@Override
public String getEaiSvcCode(StandardMessage standardMessage) {
String interfaceId = getInterfaceId(standardMessage);
String sendRecvDvcd = getSendRecvDivision(standardMessage); // S | R
String inExDivision = getInExDivision(standardMessage); // 1 | 2
if (interfaceId == null) interfaceId = "";
interfaceId = interfaceId.trim();
return interfaceId + sendRecvDvcd + StringUtils.defaultString(inExDivision);
}
// ----------------------------------------------------------------
// GUID (40자 고정)
// ----------------------------------------------------------------
@Override
public void setGuid(StandardMessage standardMessage, String guid) {
if (guid == null) throw new RuntimeException("guid is null");
if (guid.length() != GUIDGeneratorDJB.GUID_LENGTH) {
throw new RuntimeException("GUID length must be " + GUIDGeneratorDJB.GUID_LENGTH + ", actual=" + guid.length());
}
setItemValue(standardMessage, getPath(GUID), guid);
}
@Override
public String getGuid(StandardMessage standardMessage) {
return StringUtils.defaultString(getItemValue(standardMessage, getPath(GUID)));
}
// ----------------------------------------------------------------
// GUID 진행번호 — HEAD.guid_prgs_no 별도 필드
// ----------------------------------------------------------------
@Override
public String getGuidSeq(StandardMessage standardMessage) {
String val = getItemValue(standardMessage, getPath(GUID_SEQ));
if (StringUtils.isBlank(val)) return "001";
try {
// NUMBER 타입은 내부적으로 선행 0 제거 → 조회 시 3자리로 복원
return String.format("%03d", Integer.parseInt(val.trim()));
} catch (NumberFormatException e) {
return StringUtils.defaultString(val, "001");
}
}
@Override
public void setGuidSeq(StandardMessage standardMessage, String guidSeq) {
setItemValue(standardMessage, getPath(GUID_SEQ), guidSeq);
}
@Override
public String nextGuidSeq(StandardMessage standardMessage) {
String current = getGuidSeq(standardMessage);
int seq = 1;
try {
seq = Integer.parseInt(current.trim()) + 1;
} catch (NumberFormatException e) {
seq = 2;
}
String next = String.format("%03d", seq);
setGuidSeq(standardMessage, next);
return next;
}
// ----------------------------------------------------------------
// 원거래 GUID — HEAD.ortr_guid (40자 그대로)
// ----------------------------------------------------------------
@Override
public String getOrgGuid(StandardMessage standardMessage) {
return StringUtils.defaultString(getItemValue(standardMessage, getPath(GUID_ORG)));
}
@Override
public void setOrgGuid(StandardMessage standardMessage, String orgGuid) {
setItemValue(standardMessage, getPath(GUID_ORG), orgGuid);
}
// ----------------------------------------------------------------
// 처리결과구분코드: 엔진 내부(0=정상, 1=오류) ↔ DJBank(S/F)
// ----------------------------------------------------------------
@Override
public String getResponseType(StandardMessage standardMessage) {
String val = getItemValue(standardMessage, getPath(RESPONSE_TYPE));
if (PROCS_RSLT_SUCCESS.equals(val)) return STDMessageKeys.RESPONSE_TYPE_CODE_N;
if (PROCS_RSLT_FAIL.equals(val)) return STDMessageKeys.RESPONSE_TYPE_CODE_E;
return val;
}
@Override
public void setResponseType(StandardMessage standardMessage, String responseType) {
String siteVal;
if (STDMessageKeys.RESPONSE_TYPE_CODE_N.equals(responseType)) {
siteVal = PROCS_RSLT_SUCCESS;
} else if (STDMessageKeys.RESPONSE_TYPE_CODE_E.equals(responseType)) {
siteVal = PROCS_RSLT_FAIL;
} else {
siteVal = responseType;
}
setItemValue(standardMessage, getPath(RESPONSE_TYPE), siteVal);
}
// ----------------------------------------------------------------
// 원거래복원여부: Y/N 그대로 사용 (엔진 내부 1/0과 변환)
// ----------------------------------------------------------------
@Override
public String getRecoverYn(StandardMessage standardMessage) {
String val = getItemValue(standardMessage, getPath(RECOVER_YN));
return "Y".equals(val) ? "1" : "0";
}
@Override
public void setRecoverYn(StandardMessage standardMessage, String recoverYn) {
setItemValue(standardMessage, getPath(RECOVER_YN), "1".equals(recoverYn) ? "Y" : "N");
}
// ----------------------------------------------------------------
// 인터페이스ID (trim 처리)
// ----------------------------------------------------------------
@Override
public String getInterfaceId(StandardMessage standardMessage) {
String val = getItemValue(standardMessage, getPath(INTERFACE_ID));
return val == null ? "" : val.trim();
}
// ----------------------------------------------------------------
// 세션ID / 인스턴스코드 — MCI 여부에 따라 처리
// ----------------------------------------------------------------
@Override
public String getSessionId(StandardMessage standardMessage) {
EAIServerManager server = EAIServerManager.getInstance();
if (server != null && server.isMCI()) {
return StringUtils.defaultString(getItemValue(standardMessage, PATH_MCI_SESN));
}
return "";
}
@Override
public void setSessionId(StandardMessage standardMessage, String sessionId) {
EAIServerManager server = EAIServerManager.getInstance();
if (server != null && server.isMCI()) {
setItemValue(standardMessage, PATH_MCI_SESN, sessionId);
}
}
@Override
public String getInstCode(StandardMessage standardMessage) {
EAIServerManager server = EAIServerManager.getInstance();
if (server != null && server.isMCI()) {
return StringUtils.defaultString(getItemValue(standardMessage, PATH_MCI_NODE));
}
return StringUtils.defaultString(getItemValue(standardMessage, PATH_EAI_NODE));
}
@Override
public void setInstCode(StandardMessage standardMessage, String instCode) {
EAIServerManager server = EAIServerManager.getInstance();
if (server != null && server.isMCI()) {
setItemValue(standardMessage, PATH_MCI_NODE, instCode);
} else {
setItemValue(standardMessage, PATH_EAI_NODE, instCode);
}
}
// ----------------------------------------------------------------
// 요청시스템코드 — 채널유형코드(chnl_tycd)에서 추출
// ----------------------------------------------------------------
@Override
public String getReqSysCode(StandardMessage standardMessage) {
String chnlTycd = getItemValue(standardMessage, getPath(CHANNEL_TYPE_CD));
if (StringUtils.isNotBlank(chnlTycd)) {
return chnlTycd.trim();
}
// fallback: tx_id(서비스ID) 경로에서 추출
String txId = getItemValue(standardMessage, getPath(SERVICE_ID));
if (txId != null) {
String[] split = txId.split("/");
if (split.length > 1) {
String route = split[1].toUpperCase();
return route.length() > 3 ? route.substring(0, 3) : route;
}
}
return null;
}
}
@@ -0,0 +1,257 @@
package com.eactive.eai.custom.message;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedHashMap;
import java.util.Properties;
import org.apache.commons.lang3.StringUtils;
import com.eactive.eai.common.server.EAIServerManager;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.common.util.MessageUtil;
import com.eactive.eai.inbound.processor.ProcessVO;
import com.eactive.eai.message.StandardItem;
import com.eactive.eai.message.StandardMessage;
import com.eactive.eai.message.manager.StandardMessageManager;
import com.eactive.eai.message.service.DefaultStandardMessageCoordinator;
import com.eactive.eai.message.service.InterfaceMapper;
import com.ext.eai.common.stdmessage.STDMessageKeys;
/**
* DJBank(제주은행) 차세대 표준전문 Coordinator
*
* 표준전문 구조 변경에 따른 각 처리 단계 후처리 정의:
* - HEAD 평면 구조, GUID 40자, guid_prgs_no 별도 필드
* - MSG 영역: msg_dvcd(NM/EM) + MAIN_MSG + msg_list
* - 처리결과구분코드: S(성공) / F(오류)
* - 전문종료부: @JJ
*/
public class StandardMessageCoordinatorDJB extends DefaultStandardMessageCoordinator {
private static final Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
private static final DateTimeFormatter FMT_DATE = DateTimeFormatter.ofPattern("yyyyMMdd");
private static final DateTimeFormatter FMT_TIME_MILLIS = DateTimeFormatter.ofPattern("HHmmssSSS");
// HEAD 필드 경로
private static final String HEAD_FRST_MESG_DMAN_DT = "HEAD.frst_mesg_dman_dt";
private static final String HEAD_FRST_MESG_DMAN_TIME = "HEAD.frst_mesg_dman_time";
private static final String HEAD_FRST_TRNM_IPAD = "HEAD.frst_trnm_ipad";
private static final String HEAD_FRST_TRNM_IPV4_ADDR = "HEAD.frst_trnm_ipv4_addr";
private static final String HEAD_FRST_TRNM_MAC = "HEAD.frst_trnm_mac";
private static final String HEAD_SYS_ENV_DVCD = "HEAD.sys_env_dvcd";
private static final String HEAD_TRNM_SYS_DVCD = "HEAD.trnm_sys_dvcd";
private static final String HEAD_MESG_RSPN_DT = "HEAD.mesg_rspn_dt";
private static final String HEAD_MESG_RSPN_TIME = "HEAD.mesg_rspn_time";
// MSG 영역 경로
private static final String MSG_DVCD = "MSG.msg_dvcd";
private static final String MSG_SCOP_LEN = "MSG.msg_scop_len";
private static final String MSG_MAIN_MSG = "MSG.MAIN_MSG";
private static final String MSG_OUTP_ATRB_CD = "MSG.MAIN_MSG.outp_atrb_cd";
private static final String MSG_OUTP_MSG_CD = "MSG.MAIN_MSG.outp_msg_cd";
private static final String MSG_OUTP_MSG_CTNT = "MSG.MAIN_MSG.outp_msg_ctnt";
private static final String MSG_LIST_ROWCNT = "MSG.MAIN_MSG.msg_list_rowcnt";
private static final String MSG_LIST = "MSG.msg_list";
// DATA 영역 경로
private static final String DATA_SCOP_LEN = "DATA.data_scop_len";
@Override
public void coordinateAfterParsing(StandardMessage standardMessage, Object paramObject, Properties prop) {
}
@Override
public void coordinateAfterCreateMessageByRule(StandardMessage standardMessage, Object paramObject, Properties prop) {
StandardMessageManager manager = StandardMessageManager.getInstance();
InterfaceMapper mapper = manager.getMapper();
// GUID 생성 (40자) 및 설정
String guid = GUIDGeneratorDJB.getGUID("EAI");
mapper.setGuid(standardMessage, guid);
// GUID 진행번호 초기화 (최초=1)
mapper.setGuidSeq(standardMessage, "001");
// 원거래GUID = GUID 동일값 설정 (복원이 아닌 경우)
mapper.setOrgGuid(standardMessage, guid);
// 최초전문요청일자/시각 설정
LocalDateTime now = LocalDateTime.now();
standardMessage.setData(HEAD_FRST_MESG_DMAN_DT, now.format(FMT_DATE));
standardMessage.setData(HEAD_FRST_MESG_DMAN_TIME, now.format(FMT_TIME_MILLIS));
// 전송시스템구분코드 설정
standardMessage.setData(HEAD_TRNM_SYS_DVCD, "EAI");
// 시스템환경구분코드 설정 (D/T/P)
EAIServerManager eaiServer = EAIServerManager.getInstance();
standardMessage.setData(HEAD_SYS_ENV_DVCD, getSysEnvDvcd(eaiServer));
// 최초전송 IP / IPv4 / MAC 설정
setNetworkInfo(standardMessage);
}
@Override
public void coordinateBeforeStandardMessageSend(StandardMessage standardMessage, String msgType, String charset) {
makeupDataScopLen(standardMessage, charset);
}
@Override
public void coordinateBeforeResponse(StandardMessage standardMessage, ProcessVO processVO, Properties prop, String charset) {
// 응답일자/시각 설정
LocalDateTime now = LocalDateTime.now();
standardMessage.setData(HEAD_MESG_RSPN_DT, now.format(FMT_DATE));
standardMessage.setData(HEAD_MESG_RSPN_TIME, now.format(FMT_TIME_MILLIS));
makeupDataScopLen(standardMessage, charset);
}
@Override
public boolean coordinateSetStandardMessageError(StandardMessage standardMessage, InterfaceMapper mapper,
String errCode, String errMsg) {
// 처리결과 = 오류(F)
mapper.setResponseType(standardMessage, STDMessageKeys.RESPONSE_TYPE_CODE_E);
// 요청응답구분 = 응답(R)
mapper.setSendRecvDivision(standardMessage, STDMessageKeys.SEND_RECV_CD_RECV);
// 에러코드/메시지 변환
String siteErrCode = StringUtils.defaultString(MessageUtil.getTobeCode(errCode));
String siteErrMsg = StringUtils.defaultString(MessageUtil.getTobeMessage(errCode));
// MSG 영역 활성화
StandardItem msgItem = standardMessage.findItem("MSG");
if (msgItem != null) {
msgItem.setHidden(false);
msgItem.setSize(1);
}
// msg_dvcd = EM (에러메시지)
standardMessage.setData(MSG_DVCD, "EM");
// 출력속성코드 = 1(팝업)
standardMessage.setData(MSG_OUTP_ATRB_CD, "1");
// 대표 에러코드/메시지
standardMessage.setData(MSG_OUTP_MSG_CD, siteErrCode);
standardMessage.setData(MSG_OUTP_MSG_CTNT, siteErrMsg);
// msg_list 1건 구성
standardMessage.setData(MSG_LIST_ROWCNT, "00001");
StandardItem msgList = standardMessage.findItem(MSG_LIST);
if (msgList != null) {
msgList.setSize(1);
LinkedHashMap<String, StandardItem> row = msgList.getArrayChilds(0, true);
if (row != null) {
if (row.containsKey("outp_msg_cd")) row.get("outp_msg_cd").setValue(siteErrCode);
if (row.containsKey("outp_msg_ctnt")) row.get("outp_msg_ctnt").setValue(siteErrMsg);
}
}
// mapper 에러코드 설정
mapper.setErrorCode(standardMessage, siteErrCode);
mapper.setErrorMsg(standardMessage, siteErrMsg);
// msg_scop_len 계산
makeMsgScopLen(standardMessage);
// BIZ_DATA는 null 처리 (false 반환)
return false;
}
@Override
public void coordinateAfterRecvNonStdSyncResponse(StandardMessage responseMessage) {
// 처리결과 = 성공(S)
StandardMessageManager manager = StandardMessageManager.getInstance();
InterfaceMapper mapper = manager.getMapper();
mapper.setResponseType(responseMessage, STDMessageKeys.RESPONSE_TYPE_CODE_N);
// MSG 영역 활성화
StandardItem msgItem = responseMessage.findItem("MSG");
if (msgItem != null) {
msgItem.setHidden(false);
msgItem.setSize(1);
}
// msg_dvcd = NM (정상메시지)
responseMessage.setData(MSG_DVCD, "NM");
responseMessage.setData(MSG_OUTP_ATRB_CD, "0");
responseMessage.setData(MSG_OUTP_MSG_CD, "000000000000");
responseMessage.setData(MSG_OUTP_MSG_CTNT, "정상처리");
responseMessage.setData(MSG_LIST_ROWCNT, "00001");
StandardItem msgList = responseMessage.findItem(MSG_LIST);
if (msgList != null) {
msgList.setSize(1);
LinkedHashMap<String, StandardItem> row = msgList.getArrayChilds(0, true);
if (row != null) {
if (row.containsKey("outp_msg_cd")) row.get("outp_msg_cd").setValue("000000000000");
if (row.containsKey("outp_msg_ctnt")) row.get("outp_msg_ctnt").setValue("정상처리");
}
}
makeMsgScopLen(responseMessage);
}
// ----------------------------------------------------------------
// private helpers
// ----------------------------------------------------------------
private String getSysEnvDvcd(EAIServerManager server) {
if (server.isPEAIServer()) return "P"; // 운영
if (server.isSEAIServer()) return "T"; // 검증/테스트
return "D"; // 개발
}
private void setNetworkInfo(StandardMessage standardMessage) {
try {
InetAddress localAddr = InetAddress.getLocalHost();
String ipv4 = localAddr.getHostAddress();
// IPv4 주소 설정
standardMessage.setData(HEAD_FRST_TRNM_IPAD, ipv4);
standardMessage.setData(HEAD_FRST_TRNM_IPV4_ADDR, ipv4);
// MAC 주소 설정
NetworkInterface ni = NetworkInterface.getByInetAddress(localAddr);
if (ni != null) {
byte[] mac = ni.getHardwareAddress();
if (mac != null) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < mac.length; i++) {
if (i > 0) sb.append(":");
sb.append(String.format("%02X", mac[i]));
}
standardMessage.setData(HEAD_FRST_TRNM_MAC, sb.toString());
}
}
} catch (Exception e) {
if (logger.isWarn()) logger.warn("Failed to set network info", e);
}
}
private void makeupDataScopLen(StandardMessage standardMessage, String charset) {
try {
int dataLen = standardMessage.getBizDataBytes(charset).length;
String lenStr = StringUtils.leftPad(String.valueOf(dataLen), 8, '0');
standardMessage.setData(DATA_SCOP_LEN, lenStr);
} catch (Exception e) {
throw new RuntimeException("Failed to calculate data_scop_len", e);
}
}
private void makeMsgScopLen(StandardMessage standardMessage) {
try {
StandardItem mainMsg = standardMessage.findItem(MSG_MAIN_MSG);
if (mainMsg == null) return;
int len = standardMessage.getBytesDataLengthForPath(MSG_MAIN_MSG);
standardMessage.setData(MSG_SCOP_LEN, StringUtils.leftPad(String.valueOf(len), 8, '0'));
} catch (Exception e) {
if (logger.isWarn()) logger.warn("Failed to calculate msg_scop_len", e);
}
}
}
+179
View File
@@ -0,0 +1,179 @@
#-----------------------------------------------------------------------------
# comment start with #
# level; // 0 : root ~ n
# type; // 0: Message, 1: Field, 2:Group 3, Grid, 4 : Field Array, 9 : BIZ DATA
# size // 0 : variable, > 0 fixed
# fieldType; // 0: ELEMENT, 1: ATTRIBUTE,
# length;
# dataType; // 1: String, 2: Number, 10: ZZ String, 11: LL Number(LL prefix auto), 12: LL_NUMBER
#-----------------------------------------------------------------------------
# name ,level ,type ,size ,fieldType ,length ,dataType ,refPath, refValue, value
#-----------------------------------------------------------------------------
# ============================================================
# HEAD - 헤더영역 (시스템헤더부 + 공통부)
# ============================================================
HEAD,1,3,1,1,0,1,,,
stnd_mesg_len,2,2,1,1,8,12,,,
nxgn_stnd_idfr,2,2,1,1,4,1,,,JERA
guid,2,2,1,1,40,1,,,
guid_prgs_no,2,2,1,1,3,2,,,001
stnd_mesg_ver,2,2,1,1,3,1,,,R10
ortr_guid,2,2,1,1,40,1,,,
sect_ecrpt_yn,2,2,1,1,1,1,,,N
frst_trnm_ipad,2,2,1,1,40,1,,,
frst_trnm_ipv4_addr,2,2,1,1,15,1,,,
frst_trnm_mac,2,2,1,1,17,1,,,
frst_mesg_dman_dt,2,2,1,1,8,1,,,
frst_mesg_dman_time,2,2,1,1,9,1,,,
frst_trnm_sys_dvcd,2,2,1,1,3,1,,,OPA
trnm_sys_dvcd,2,2,1,1,3,1,,,EAI
mesg_rspn_dt,2,2,1,1,8,1,,,
mesg_rspn_time,2,2,1,1,9,1,,,
dman_rspn_dvcd,2,2,1,1,1,1,,,S
otsd_tmot_occu_rspn_yn,2,2,1,1,1,1,,,
sys_env_dvcd,2,2,1,1,1,1,,,D
tx_tycd,2,2,1,1,1,1,,,O
synz_dvcd,2,2,1,1,1,1,,,S
tx_id,2,2,1,1,12,1,,,
procs_rslt_dvcd,2,2,1,1,1,1,,,S
procs_rslt_romsg_tx_id,2,2,1,1,12,1,,,
chnl_tycd,2,2,1,1,3,1,,,EAI
chnl_dtls_clcd,2,2,1,1,3,1,,,
xtis_cd,2,2,1,1,3,1,,,
osdch_dvcd,2,2,1,1,3,1,,,
lnkd_seqno,2,2,1,1,3,2,,,
if_id,2,2,1,1,30,1,,,
hmab_dvcd,2,2,1,1,1,1,,,
mci_sesn_id,2,2,1,1,8,1,,,
mci_node_dvcd,2,2,1,1,2,1,,,
eai_node_dvcd,2,2,1,1,2,1,,,
fep_node_dvcd,2,2,1,1,2,1,,,
fep_sesn_id,2,2,1,1,8,1,,,
ortr_restr_yn,2,2,1,1,1,1,,,
filler,2,2,1,1,40,1,,,
input_mesg_tycd,2,2,1,1,1,1,,,
outp_mesg_tycd,2,2,1,1,1,1,,,
mesg_cnty_seqno,2,2,1,1,3,2,,,
msg_trnm_tycd,2,2,1,1,1,1,,,
msg_trnm_brcd,2,2,1,1,3,1,,,
msg_trnm_tlrno,2,2,1,1,6,1,,,
tx_cmgr_cd,2,2,1,1,4,1,,,
mgmt_brcd,2,2,1,1,3,1,,,
tx_brcd,2,2,1,1,3,1,,,
insl_brcd,2,2,1,1,3,1,,,
blng_brcd,2,2,1,1,3,1,,,
corp_tlwn_virt_brcd,2,2,1,1,3,1,,,
tlrno,2,2,1,1,6,1,,,
telr_jcls_cd,2,2,1,1,2,1,,,
clsn_bfaf_dvcd,2,2,1,1,1,1,,,
tlwn_dvcd,2,2,1,1,1,1,,,
scfc_tmnl_dvcd,2,2,1,1,2,1,,,
telr_cnfr_trgt_yn,2,2,1,1,1,1,,,
telr_cnfr_yn,2,2,1,1,1,1,,,
prcg_aprv_typ_dvcd,2,2,1,1,1,1,,,
sq1_aprv_media_dvcd,2,2,1,1,1,1,,,
sq1_aprv_prcg_empno,2,2,1,1,6,1,,,
sq1_aprv_prcg_athn_no,2,2,1,1,32,1,,,
sq2_aprv_media_dvcd,2,2,1,1,1,1,,,
sq2_aprv_prcg_empno,2,2,1,1,6,1,,,
sq2_aprv_prcg_athn_no,2,2,1,1,32,1,,,
main_scn_id,2,2,1,1,12,1,,,
tx_scn_id,2,2,1,1,12,1,,,
pb_seqno,2,2,1,1,5,2,,,
pb_ms_read_yn,2,2,1,1,1,1,,,
pb_print_conn_yn,2,2,1,1,1,1,,,
dgtl_tlwn_dvcd,2,2,1,1,1,1,,,
idc_scan_rnno,2,2,1,1,32,1,,,
idc_scan_no,2,2,1,1,25,1,,,
ctsed_dt,2,2,1,1,8,1,,,
reckn_dt,2,2,1,1,8,1,,,
slip_no,2,2,1,1,5,2,,,
gnrz_tmot_tktm,2,2,1,1,3,2,,,35
tx_tmot_tktm,2,2,1,1,3,2,,,30
idvd_info_iqry_prps_dvcd,2,2,1,1,3,1,,,
idvd_info_iqry_rsn,2,2,1,1,100,1,,,
rprs_msg_cd,2,2,1,1,12,1,,,
# ============================================================
# EZDATA - 전자금융공통영역 (corp_tlwn_virt_brcd=ERP 조건부)
# ============================================================
EZDATA,1,3,1,1,0,1,HEAD.corp_tlwn_virt_brcd,ERP,
login_mhod_dvcd,2,2,1,1,1,1,,,
elfn_bnkn_dvcd,2,2,1,1,2,1,,,01
usr_no,2,2,1,1,16,1,,,
rgsr_id,2,2,1,1,16,1,,,
svr_tx_seqno,2,2,1,1,10,2,,,
tx_seqno,2,2,1,1,10,2,,,
priqr_tx_seqno,2,2,1,1,10,2,,,
secu_media_dvcd,2,2,1,1,2,1,,,00
secu_media_sta_dvcd,2,2,1,1,2,1,,,00
brll_srcd_yn,2,2,1,1,1,1,,,N
sq1_srcd_indc_no,2,2,1,1,2,2,,,
sq1_srcd_pswd,2,2,1,1,32,1,,,
sq2_srcd_indc_no,2,2,1,1,2,2,,,
sq2_srcd_pswd,2,2,1,1,32,1,,,
otp_athn_val,2,2,1,1,6,1,,,
secu_media_seqno_dman_val,2,2,1,1,4,1,,,
secu_media_seqno_athn_val,2,2,1,1,4,1,,,
next_data_exis_yn,2,2,1,1,1,1,,,
page_no,2,2,1,1,5,2,,,
page_size,2,2,1,1,5,2,,,
ttcnt,2,2,1,1,5,2,,,
iqry_ccnt,2,2,1,1,5,2,,,
next_data_info,2,2,1,1,100,1,,,
cstno,2,2,1,1,10,2,,,
otp_expr_gdnc_yn,2,2,1,1,1,1,,,N
dup_tx_yn,2,2,1,1,1,1,,,N
cpu_id_no,2,2,1,1,64,1,,,
elfn_mac,2,2,1,1,17,1,,,
hdd_srial_no,2,2,1,1,64,1,,,
main_board_srial_no,2,2,1,1,64,1,,,
pc_ofcl_ipad,2,2,1,1,40,1,,,
pc_prvat_ipad,2,2,1,1,40,1,,,
smph_old_unq_no,2,2,1,1,32,1,,,
smph_nw_unq_no,2,2,1,1,32,1,,,
smph_mac,2,2,1,1,12,1,,,
smph_modl_no,2,2,1,1,20,1,,,
ostp_cd,2,2,1,1,1,1,,,
mcco_dvcd,2,2,1,1,1,1,,,
elfn_use_tlno,2,2,1,1,12,1,,,
addt_athn_yn,2,2,1,1,1,1,,,
addt_athn_meth_dvcd,2,2,1,1,1,1,,,
abr_ip_yn,2,2,1,1,1,1,,,N
login_dt,2,2,1,1,8,1,,,
login_time,2,2,1,1,6,1,,,
cst_nm,2,2,1,1,100,1,,,
aprv_aprvl_rol_dvcd,2,2,1,1,1,1,,,
elfn_spr_fild,2,2,1,1,698,1,,,
# ============================================================
# MSG - 메시지영역 (dman_rspn_dvcd != S 조건부, 응답 시)
# ============================================================
MSG,1,3,0,1,0,1,HEAD.dman_rspn_dvcd,!S,
msg_dvcd,2,2,0,1,2,1,,,NM
msg_scop_len,2,2,0,1,8,2,,,
MAIN_MSG,2,3,0,1,0,1,,,
outp_atrb_cd,3,2,1,1,1,1,,,0
outp_msg_cd,3,2,1,1,12,1,,,
outp_msg_ctnt,3,2,1,1,200,1,,,
outp_msg_desc,3,2,1,1,300,1,,,
mngm_msg_cd,3,2,1,1,12,1,,,
msg_list_rowcnt,3,2,0,1,5,2,,,00000
msg_list,2,4,0,1,0,1,MSG.MAIN_MSG.msg_list_rowcnt,,
outp_msg_cd,3,2,0,1,12,1,,,
outp_msg_ctnt,3,2,0,1,200,1,,,
outp_msg_desc,3,2,0,1,300,1,,,
mngm_msg_cd,3,2,0,1,12,1,,,
err_occu_item_nm,3,2,0,1,50,1,,,
err_occu_loct,3,2,0,1,300,1,,,
err_chgr_nm,3,2,0,1,10,1,,,
err_chrg_cnpl_no,3,2,0,1,20,1,,,
# ============================================================
# DATA - 데이터부
# ============================================================
DATA,1,3,1,1,0,1,,,
data_dvcd,2,2,1,1,2,1,,,IO
data_scop_len,2,2,1,1,8,2,,,
BIZ_DATA,2,9,1,1,0,1,,,
# ============================================================
# 전문종료부 (@JJ, 3자 고정)
# ============================================================
MESG_END_IDFR_VAL,1,2,1,1,3,10,,,@JJ
1 #-----------------------------------------------------------------------------
2 # comment start with #
3 # level; // 0 : root ~ n
4 # type; // 0: Message, 1: Field, 2:Group 3, Grid, 4 : Field Array, 9 : BIZ DATA
5 # size // 0 : variable, > 0 fixed
6 # fieldType; // 0: ELEMENT, 1: ATTRIBUTE,
7 # length;
8 # dataType; // 1: String, 2: Number, 10: ZZ String, 11: LL Number(LL prefix auto), 12: LL_NUMBER
9 #-----------------------------------------------------------------------------
10 # name ,level ,type ,size ,fieldType ,length ,dataType ,refPath, refValue, value
11 #-----------------------------------------------------------------------------
12 # ============================================================
13 # HEAD - 헤더영역 (시스템헤더부 + 공통부)
14 # ============================================================
15 HEAD,1,3,1,1,0,1,,,
16 stnd_mesg_len,2,2,1,1,8,12,,,
17 nxgn_stnd_idfr,2,2,1,1,4,1,,,JERA
18 guid,2,2,1,1,40,1,,,
19 guid_prgs_no,2,2,1,1,3,2,,,001
20 stnd_mesg_ver,2,2,1,1,3,1,,,R10
21 ortr_guid,2,2,1,1,40,1,,,
22 sect_ecrpt_yn,2,2,1,1,1,1,,,N
23 frst_trnm_ipad,2,2,1,1,40,1,,,
24 frst_trnm_ipv4_addr,2,2,1,1,15,1,,,
25 frst_trnm_mac,2,2,1,1,17,1,,,
26 frst_mesg_dman_dt,2,2,1,1,8,1,,,
27 frst_mesg_dman_time,2,2,1,1,9,1,,,
28 frst_trnm_sys_dvcd,2,2,1,1,3,1,,,OPA
29 trnm_sys_dvcd,2,2,1,1,3,1,,,EAI
30 mesg_rspn_dt,2,2,1,1,8,1,,,
31 mesg_rspn_time,2,2,1,1,9,1,,,
32 dman_rspn_dvcd,2,2,1,1,1,1,,,S
33 otsd_tmot_occu_rspn_yn,2,2,1,1,1,1,,,
34 sys_env_dvcd,2,2,1,1,1,1,,,D
35 tx_tycd,2,2,1,1,1,1,,,O
36 synz_dvcd,2,2,1,1,1,1,,,S
37 tx_id,2,2,1,1,12,1,,,
38 procs_rslt_dvcd,2,2,1,1,1,1,,,S
39 procs_rslt_romsg_tx_id,2,2,1,1,12,1,,,
40 chnl_tycd,2,2,1,1,3,1,,,EAI
41 chnl_dtls_clcd,2,2,1,1,3,1,,,
42 xtis_cd,2,2,1,1,3,1,,,
43 osdch_dvcd,2,2,1,1,3,1,,,
44 lnkd_seqno,2,2,1,1,3,2,,,
45 if_id,2,2,1,1,30,1,,,
46 hmab_dvcd,2,2,1,1,1,1,,,
47 mci_sesn_id,2,2,1,1,8,1,,,
48 mci_node_dvcd,2,2,1,1,2,1,,,
49 eai_node_dvcd,2,2,1,1,2,1,,,
50 fep_node_dvcd,2,2,1,1,2,1,,,
51 fep_sesn_id,2,2,1,1,8,1,,,
52 ortr_restr_yn,2,2,1,1,1,1,,,
53 filler,2,2,1,1,40,1,,,
54 input_mesg_tycd,2,2,1,1,1,1,,,
55 outp_mesg_tycd,2,2,1,1,1,1,,,
56 mesg_cnty_seqno,2,2,1,1,3,2,,,
57 msg_trnm_tycd,2,2,1,1,1,1,,,
58 msg_trnm_brcd,2,2,1,1,3,1,,,
59 msg_trnm_tlrno,2,2,1,1,6,1,,,
60 tx_cmgr_cd,2,2,1,1,4,1,,,
61 mgmt_brcd,2,2,1,1,3,1,,,
62 tx_brcd,2,2,1,1,3,1,,,
63 insl_brcd,2,2,1,1,3,1,,,
64 blng_brcd,2,2,1,1,3,1,,,
65 corp_tlwn_virt_brcd,2,2,1,1,3,1,,,
66 tlrno,2,2,1,1,6,1,,,
67 telr_jcls_cd,2,2,1,1,2,1,,,
68 clsn_bfaf_dvcd,2,2,1,1,1,1,,,
69 tlwn_dvcd,2,2,1,1,1,1,,,
70 scfc_tmnl_dvcd,2,2,1,1,2,1,,,
71 telr_cnfr_trgt_yn,2,2,1,1,1,1,,,
72 telr_cnfr_yn,2,2,1,1,1,1,,,
73 prcg_aprv_typ_dvcd,2,2,1,1,1,1,,,
74 sq1_aprv_media_dvcd,2,2,1,1,1,1,,,
75 sq1_aprv_prcg_empno,2,2,1,1,6,1,,,
76 sq1_aprv_prcg_athn_no,2,2,1,1,32,1,,,
77 sq2_aprv_media_dvcd,2,2,1,1,1,1,,,
78 sq2_aprv_prcg_empno,2,2,1,1,6,1,,,
79 sq2_aprv_prcg_athn_no,2,2,1,1,32,1,,,
80 main_scn_id,2,2,1,1,12,1,,,
81 tx_scn_id,2,2,1,1,12,1,,,
82 pb_seqno,2,2,1,1,5,2,,,
83 pb_ms_read_yn,2,2,1,1,1,1,,,
84 pb_print_conn_yn,2,2,1,1,1,1,,,
85 dgtl_tlwn_dvcd,2,2,1,1,1,1,,,
86 idc_scan_rnno,2,2,1,1,32,1,,,
87 idc_scan_no,2,2,1,1,25,1,,,
88 ctsed_dt,2,2,1,1,8,1,,,
89 reckn_dt,2,2,1,1,8,1,,,
90 slip_no,2,2,1,1,5,2,,,
91 gnrz_tmot_tktm,2,2,1,1,3,2,,,35
92 tx_tmot_tktm,2,2,1,1,3,2,,,30
93 idvd_info_iqry_prps_dvcd,2,2,1,1,3,1,,,
94 idvd_info_iqry_rsn,2,2,1,1,100,1,,,
95 rprs_msg_cd,2,2,1,1,12,1,,,
96 # ============================================================
97 # EZDATA - 전자금융공통영역 (corp_tlwn_virt_brcd=ERP 조건부)
98 # ============================================================
99 EZDATA,1,3,1,1,0,1,HEAD.corp_tlwn_virt_brcd,ERP,
100 login_mhod_dvcd,2,2,1,1,1,1,,,
101 elfn_bnkn_dvcd,2,2,1,1,2,1,,,01
102 usr_no,2,2,1,1,16,1,,,
103 rgsr_id,2,2,1,1,16,1,,,
104 svr_tx_seqno,2,2,1,1,10,2,,,
105 tx_seqno,2,2,1,1,10,2,,,
106 priqr_tx_seqno,2,2,1,1,10,2,,,
107 secu_media_dvcd,2,2,1,1,2,1,,,00
108 secu_media_sta_dvcd,2,2,1,1,2,1,,,00
109 brll_srcd_yn,2,2,1,1,1,1,,,N
110 sq1_srcd_indc_no,2,2,1,1,2,2,,,
111 sq1_srcd_pswd,2,2,1,1,32,1,,,
112 sq2_srcd_indc_no,2,2,1,1,2,2,,,
113 sq2_srcd_pswd,2,2,1,1,32,1,,,
114 otp_athn_val,2,2,1,1,6,1,,,
115 secu_media_seqno_dman_val,2,2,1,1,4,1,,,
116 secu_media_seqno_athn_val,2,2,1,1,4,1,,,
117 next_data_exis_yn,2,2,1,1,1,1,,,
118 page_no,2,2,1,1,5,2,,,
119 page_size,2,2,1,1,5,2,,,
120 ttcnt,2,2,1,1,5,2,,,
121 iqry_ccnt,2,2,1,1,5,2,,,
122 next_data_info,2,2,1,1,100,1,,,
123 cstno,2,2,1,1,10,2,,,
124 otp_expr_gdnc_yn,2,2,1,1,1,1,,,N
125 dup_tx_yn,2,2,1,1,1,1,,,N
126 cpu_id_no,2,2,1,1,64,1,,,
127 elfn_mac,2,2,1,1,17,1,,,
128 hdd_srial_no,2,2,1,1,64,1,,,
129 main_board_srial_no,2,2,1,1,64,1,,,
130 pc_ofcl_ipad,2,2,1,1,40,1,,,
131 pc_prvat_ipad,2,2,1,1,40,1,,,
132 smph_old_unq_no,2,2,1,1,32,1,,,
133 smph_nw_unq_no,2,2,1,1,32,1,,,
134 smph_mac,2,2,1,1,12,1,,,
135 smph_modl_no,2,2,1,1,20,1,,,
136 ostp_cd,2,2,1,1,1,1,,,
137 mcco_dvcd,2,2,1,1,1,1,,,
138 elfn_use_tlno,2,2,1,1,12,1,,,
139 addt_athn_yn,2,2,1,1,1,1,,,
140 addt_athn_meth_dvcd,2,2,1,1,1,1,,,
141 abr_ip_yn,2,2,1,1,1,1,,,N
142 login_dt,2,2,1,1,8,1,,,
143 login_time,2,2,1,1,6,1,,,
144 cst_nm,2,2,1,1,100,1,,,
145 aprv_aprvl_rol_dvcd,2,2,1,1,1,1,,,
146 elfn_spr_fild,2,2,1,1,698,1,,,
147 # ============================================================
148 # MSG - 메시지영역 (dman_rspn_dvcd != S 조건부, 응답 시)
149 # ============================================================
150 MSG,1,3,0,1,0,1,HEAD.dman_rspn_dvcd,!S,
151 msg_dvcd,2,2,0,1,2,1,,,NM
152 msg_scop_len,2,2,0,1,8,2,,,
153 MAIN_MSG,2,3,0,1,0,1,,,
154 outp_atrb_cd,3,2,1,1,1,1,,,0
155 outp_msg_cd,3,2,1,1,12,1,,,
156 outp_msg_ctnt,3,2,1,1,200,1,,,
157 outp_msg_desc,3,2,1,1,300,1,,,
158 mngm_msg_cd,3,2,1,1,12,1,,,
159 msg_list_rowcnt,3,2,0,1,5,2,,,00000
160 msg_list,2,4,0,1,0,1,MSG.MAIN_MSG.msg_list_rowcnt,,
161 outp_msg_cd,3,2,0,1,12,1,,,
162 outp_msg_ctnt,3,2,0,1,200,1,,,
163 outp_msg_desc,3,2,0,1,300,1,,,
164 mngm_msg_cd,3,2,0,1,12,1,,,
165 err_occu_item_nm,3,2,0,1,50,1,,,
166 err_occu_loct,3,2,0,1,300,1,,,
167 err_chgr_nm,3,2,0,1,10,1,,,
168 err_chrg_cnpl_no,3,2,0,1,20,1,,,
169 # ============================================================
170 # DATA - 데이터부
171 # ============================================================
172 DATA,1,3,1,1,0,1,,,
173 data_dvcd,2,2,1,1,2,1,,,IO
174 data_scop_len,2,2,1,1,8,2,,,
175 BIZ_DATA,2,9,1,1,0,1,,,
176 # ============================================================
177 # 전문종료부 (@JJ, 3자 고정)
178 # ============================================================
179 MESG_END_IDFR_VAL,1,2,1,1,3,10,,,@JJ
@@ -1,18 +1,23 @@
# layout : StandardMessage layout definition
#layout.file.type=CSV
layout.file.type=DB
#layout.file.type=DB
layout.file.type=CSV
#layout.file.path=standard-layout-kjb.csv
#layout.file.path=standard-layout-elk.csv
layout.file.path=standard-layout-djb.csv
#layout.filter.FLAT=com.eactive.eai.custom.message.FlatMessageFilterSBI
layout.filter.FLAT=com.eactive.eai.message.filter.FlatMessageFilter
# mapper : StandardMessage's fields getter/setter interface
#mapper.class=com.eactive.eai.custom.message.InterfaceMapperSBI
mapper.class=com.eactive.eai.custom.message.InterfaceMapperKJB
#mapper.class=com.eactive.eai.custom.message.InterfaceMapperKJB
mapper.class=com.eactive.eai.custom.message.InterfaceMapperDJB
#mapper.definition=standard-message-mapping-config-sbi.properties
#mapper.definition=standard-message-mapping-config-elk.properties
mapper.definition=standard-message-mapping-config-kjb.properties
#mapper.definition=standard-message-mapping-config-kjb.properties
mapper.definition=standard-message-mapping-config-djb.properties
# StandardMessage Coordinator implementation
message.coordinator.class=com.eactive.eai.custom.message.StandardMessageCoordinatorKJB
#message.coordinator.class=com.eactive.eai.custom.message.StandardMessageCoordinatorKJB
message.coordinator.class=com.eactive.eai.custom.message.StandardMessageCoordinatorDJB
# RequestProcessor implementation
#requestProcessor.class=com.eactive.eai.inbound.processor.RequestProcessor
# reader : parsing input data to StandardMessage
@@ -0,0 +1,30 @@
# DJBank(제주은행) 표준전문 필드 매핑 설정
# InterfaceMapper 논리키 = 표준전문 필드 경로
# HEAD 영역 (평면 구조)
GUID=HEAD.guid
GUID_SEQ=HEAD.guid_prgs_no
GUID_ORG=HEAD.ortr_guid
SERVICE_ID=HEAD.tx_id
INTERFACE_ID=HEAD.if_id
SEND_RECV_DIVISION=HEAD.dman_rspn_dvcd
IN_EX_DIVISION=HEAD.hmab_dvcd
OPERATION_ENV=HEAD.sys_env_dvcd
FIRST_REQ_IP=HEAD.frst_trnm_ipad
RECOVER_YN=HEAD.ortr_restr_yn
SESSION_ID=HEAD.mci_sesn_id
SYNC_ASYNC_TYPE=HEAD.synz_dvcd
CHANNEL_TYPE_CD=HEAD.chnl_tycd
CHANNEL_DETAIL_CD=HEAD.chnl_dtls_clcd
SEND_TIME=HEAD.frst_mesg_dman_time
RECV_TIME=HEAD.mesg_rspn_time
SYSTEM_TYPE=HEAD.trnm_sys_dvcd
TIMEOUT=HEAD.gnrz_tmot_tktm
INST_CODE=HEAD.eai_node_dvcd
USER_ID=HEAD.tlrno
REQ_SYS_CODE=HEAD.chnl_tycd
# MSG 영역 (응답 시 활성화)
ERROR_CODE=MSG.MAIN_MSG.outp_msg_cd
ERROR_MSG=MSG.MAIN_MSG.outp_msg_ctnt
RESPONSE_TYPE=HEAD.procs_rslt_dvcd
RETURN_VALUE=
RETURN_SERVICE_ID=
@@ -0,0 +1,82 @@
package com.eactive.eai.custom.message;
import static org.junit.jupiter.api.Assertions.*;
import java.util.HashSet;
import java.util.Set;
import org.junit.jupiter.api.Test;
class GUIDGeneratorDJBTest {
@Test
void guid_길이는_40자여야_한다() {
String guid = GUIDGeneratorDJB.getGUID("EAI");
assertEquals(40, guid.length(), "GUID 길이는 40자: " + guid);
}
@Test
void guid_시스템코드_3자로_정규화된다() {
// 짧은 코드
String guid1 = GUIDGeneratorDJB.getGUID("EA");
assertEquals(40, guid1.length());
// 긴 코드 (잘림)
String guid2 = GUIDGeneratorDJB.getGUID("EAIFEP");
assertEquals(40, guid2.length());
// null
String guid3 = GUIDGeneratorDJB.getGUID(null);
assertEquals(40, guid3.length());
}
@Test
void guid_구성_형식_검증() {
String guid = GUIDGeneratorDJB.getGUID("EAI");
// 일자(8) + 시간(6) + 밀리초(3) + 시스템코드(3) + 노드번호(2) + 세션ID(12) + Random(6)
String date = guid.substring(0, 8);
String time = guid.substring(8, 14);
String millis = guid.substring(14, 17);
String sysCode = guid.substring(17, 20);
String nodeNo = guid.substring(20, 22);
String sessId = guid.substring(22, 34);
String random = guid.substring(34, 40);
// 일자: 숫자 8자리
assertDoesNotThrow(() -> Long.parseLong(date), "일자 부분이 숫자가 아님: " + date);
assertTrue(date.matches("\\d{8}"), "일자 형식 오류: " + date);
// 시간: 숫자 6자리
assertTrue(time.matches("\\d{6}"), "시간 형식 오류: " + time);
// 밀리초: 숫자 3자리
assertTrue(millis.matches("\\d{3}"), "밀리초 형식 오류: " + millis);
// 시스템코드: 3자리 영문/숫자
assertEquals(3, sysCode.length(), "시스템코드 길이 오류: " + sysCode);
// 노드번호: 2자리
assertEquals(2, nodeNo.length(), "노드번호 길이 오류: " + nodeNo);
// 세션ID: 12자리
assertEquals(12, sessId.length(), "세션ID 길이 오류: " + sessId);
// Random: 숫자 6자리
assertTrue(random.matches("\\d{6}"), "Random 형식 오류: " + random);
}
@Test
void guid_연속_생성시_유니크해야_한다() {
Set<String> guids = new HashSet<>();
int count = 1000;
for (int i = 0; i < count; i++) {
guids.add(GUIDGeneratorDJB.getGUID("EAI"));
}
assertEquals(count, guids.size(), "GUID 중복 발생");
}
@Test
void guid_상수_길이값_확인() {
assertEquals(40, GUIDGeneratorDJB.GUID_LENGTH);
}
}
@@ -0,0 +1,218 @@
package com.eactive.eai.custom.message;
import static org.junit.jupiter.api.Assertions.*;
import java.util.HashMap;
import java.util.Properties;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import com.eactive.eai.message.StandardMessage;
import com.eactive.eai.message.StandardMessageUtil;
import com.ext.eai.common.stdmessage.STDMessageKeys;
class InterfaceMapperDJBTest {
private InterfaceMapperDJB mapper;
private StandardMessage message;
@BeforeEach
void setUp() throws Exception {
// CSV에서 표준전문 레이아웃 로드
message = StandardMessageUtil.generateMessageFromCsvFile(
"src/main/resources/standard-layout-djb.csv");
assertNotNull(message, "standard-layout-djb.csv 로드 실패");
message.setReadPosition(0);
// 매핑 설정 로드
Properties props = new Properties();
try (java.io.InputStream in = getClass().getClassLoader()
.getResourceAsStream("standard-message-mapping-config-djb.properties")) {
assertNotNull(in, "standard-message-mapping-config-djb.properties 로드 실패");
props.load(in);
}
HashMap<String, String> pathMap = new HashMap<>();
for (String key : props.stringPropertyNames()) {
pathMap.put(key.trim(), props.getProperty(key).trim());
}
mapper = new InterfaceMapperDJB();
mapper.initPathMap(pathMap);
}
// ----------------------------------------------------------------
// GUID
// ----------------------------------------------------------------
@Test
void setGuid_40자_정상_설정() {
String guid = GUIDGeneratorDJB.getGUID("EAI");
mapper.setGuid(message, guid);
assertEquals(guid, mapper.getGuid(message));
}
@Test
void setGuid_40자_아닌경우_예외발생() {
assertThrows(RuntimeException.class, () -> mapper.setGuid(message, "SHORT"));
}
@Test
void setGuid_null이면_예외발생() {
assertThrows(RuntimeException.class, () -> mapper.setGuid(message, null));
}
// ----------------------------------------------------------------
// GUID 진행번호 (guid_prgs_no - 별도 필드)
// ----------------------------------------------------------------
@Test
void guidSeq_초기값_및_nextGuidSeq_증가() {
// 초기값 설정
mapper.setGuidSeq(message, "001");
assertEquals("001", mapper.getGuidSeq(message));
// +1 증가
String next = mapper.nextGuidSeq(message);
assertEquals("002", next);
assertEquals("002", mapper.getGuidSeq(message));
}
@Test
void nextGuidSeq_3자리_zero_padding() {
mapper.setGuidSeq(message, "009");
assertEquals("010", mapper.nextGuidSeq(message));
mapper.setGuidSeq(message, "099");
assertEquals("100", mapper.nextGuidSeq(message));
}
// ----------------------------------------------------------------
// 원거래 GUID (ortr_guid)
// ----------------------------------------------------------------
@Test
void orgGuid_설정_조회() {
String guid = GUIDGeneratorDJB.getGUID("EAI");
mapper.setOrgGuid(message, guid);
assertEquals(guid, mapper.getOrgGuid(message));
}
// ----------------------------------------------------------------
// 처리결과구분코드 (S/F ↔ 엔진 내부 NR/ER)
// ----------------------------------------------------------------
@Test
void setResponseType_정상_NR_to_S() {
mapper.setResponseType(message, STDMessageKeys.RESPONSE_TYPE_CODE_N); // "NR"
assertEquals("S", message.findItemValue("HEAD.procs_rslt_dvcd"));
}
@Test
void setResponseType_오류_ER_to_F() {
mapper.setResponseType(message, STDMessageKeys.RESPONSE_TYPE_CODE_E); // "ER"
assertEquals("F", message.findItemValue("HEAD.procs_rslt_dvcd"));
}
@Test
void getResponseType_S_to_NR() {
message.setData("HEAD.procs_rslt_dvcd", "S");
assertEquals(STDMessageKeys.RESPONSE_TYPE_CODE_N, mapper.getResponseType(message));
}
@Test
void getResponseType_F_to_ER() {
message.setData("HEAD.procs_rslt_dvcd", "F");
assertEquals(STDMessageKeys.RESPONSE_TYPE_CODE_E, mapper.getResponseType(message));
}
// ----------------------------------------------------------------
// 원거래복원여부 (Y/N ↔ 엔진 내부 1/0)
// ----------------------------------------------------------------
@Test
void recoverYn_Y면_1반환() {
message.setData("HEAD.ortr_restr_yn", "Y");
assertEquals("1", mapper.getRecoverYn(message));
}
@Test
void recoverYn_N면_0반환() {
message.setData("HEAD.ortr_restr_yn", "N");
assertEquals("0", mapper.getRecoverYn(message));
}
@Test
void setRecoverYn_1이면_Y설정() {
mapper.setRecoverYn(message, "1");
assertEquals("Y", message.findItemValue("HEAD.ortr_restr_yn"));
}
@Test
void setRecoverYn_0이면_N설정() {
mapper.setRecoverYn(message, "0");
assertEquals("N", message.findItemValue("HEAD.ortr_restr_yn"));
}
// ----------------------------------------------------------------
// 인터페이스ID (trim)
// ----------------------------------------------------------------
@Test
void getInterfaceId_공백_trim() {
message.setData("HEAD.if_id", " IF001 ");
assertEquals("IF001", mapper.getInterfaceId(message));
}
@Test
void getInterfaceId_null이면_빈문자열() {
// 초기 공백상태
String ifId = mapper.getInterfaceId(message);
assertNotNull(ifId);
assertEquals("", ifId.trim());
}
// ----------------------------------------------------------------
// EAI 서비스코드 조합
// ----------------------------------------------------------------
@Test
void getEaiSvcCode_인터페이스ID_요청응답_내외구분_조합() {
message.setData("HEAD.if_id", "IF_TEST_001");
message.setData("HEAD.dman_rspn_dvcd", "S");
message.setData("HEAD.hmab_dvcd", "1");
String svcCode = mapper.getEaiSvcCode(message);
assertTrue(svcCode.startsWith("IF_TEST_001"), "EAI 서비스코드: " + svcCode);
assertTrue(svcCode.contains("S"), "요청응답구분 포함: " + svcCode);
}
// ----------------------------------------------------------------
// 필드 경로 기본 동작 확인 (매핑 설정 유효성)
// ----------------------------------------------------------------
@Test
void sendRecvDivision_설정_조회() {
mapper.setSendRecvDivision(message, "R");
assertEquals("R", mapper.getSendRecvDivision(message));
}
@Test
void inExDivision_설정_조회() {
mapper.setInExDivision(message, "1");
assertEquals("1", mapper.getInExDivision(message));
}
@Test
void errorCode_설정_조회() {
mapper.setErrorCode(message, "ERR001");
assertEquals("ERR001", mapper.getErrorCode(message));
}
@Test
void errorMsg_설정_조회() {
mapper.setErrorMsg(message, "오류가 발생했습니다.");
assertEquals("오류가 발생했습니다.", mapper.getErrorMsg(message));
}
}
@@ -0,0 +1,163 @@
package com.eactive.eai.custom.message;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import com.eactive.eai.message.StandardItem;
import com.eactive.eai.message.StandardMessage;
import com.eactive.eai.message.StandardMessageUtil;
/**
* standard-layout-djb.csv 로드 및 전문 구조 검증
*/
class StandardLayoutDJBTest {
private StandardMessage message;
@BeforeEach
void setUp() {
message = StandardMessageUtil.generateMessageFromCsvFile(
"src/main/resources/standard-layout-djb.csv");
assertNotNull(message, "standard-layout-djb.csv 로드 실패");
message.setReadPosition(0);
}
// ----------------------------------------------------------------
// 최상위 블록 존재 여부
// ----------------------------------------------------------------
@Test
void HEAD_블록_존재() {
assertNotNull(message.findItem("HEAD"), "HEAD 블록 없음");
}
@Test
void EZDATA_블록_존재() {
assertNotNull(message.findItem("EZDATA"), "EZDATA 블록 없음");
}
@Test
void MSG_블록_존재() {
assertNotNull(message.findItem("MSG"), "MSG 블록 없음");
}
@Test
void DATA_블록_존재() {
assertNotNull(message.findItem("DATA"), "DATA 블록 없음");
}
@Test
void 전문종료부_존재() {
assertNotNull(message.findItem("MESG_END_IDFR_VAL"), "전문종료부 없음");
}
// ----------------------------------------------------------------
// HEAD 핵심 필드 검증
// ----------------------------------------------------------------
@Test
void HEAD_guid_필드_존재_및_길이40() {
StandardItem guidItem = message.findItem("HEAD.guid");
assertNotNull(guidItem, "HEAD.guid 필드 없음");
assertEquals(40, guidItem.getLength(), "HEAD.guid 길이는 40자여야 함");
}
@Test
void HEAD_guid_prgs_no_필드_존재() {
StandardItem item = message.findItem("HEAD.guid_prgs_no");
assertNotNull(item, "HEAD.guid_prgs_no 필드 없음");
assertEquals(3, item.getLength());
}
@Test
void HEAD_nxgn_stnd_idfr_기본값_JERA() {
StandardItem item = message.findItem("HEAD.nxgn_stnd_idfr");
assertNotNull(item, "HEAD.nxgn_stnd_idfr 필드 없음");
assertEquals(4, item.getLength());
assertEquals("JERA", item.getValue());
}
@Test
void HEAD_ortr_guid_필드_존재_및_길이40() {
StandardItem item = message.findItem("HEAD.ortr_guid");
assertNotNull(item, "HEAD.ortr_guid 필드 없음");
assertEquals(40, item.getLength());
}
@Test
void HEAD_if_id_필드_길이30() {
StandardItem item = message.findItem("HEAD.if_id");
assertNotNull(item, "HEAD.if_id 필드 없음");
assertEquals(30, item.getLength(), "HEAD.if_id 길이는 30자여야 함 (기존 20자에서 변경)");
}
@Test
void HEAD_dman_rspn_dvcd_기본값_S() {
StandardItem item = message.findItem("HEAD.dman_rspn_dvcd");
assertNotNull(item, "HEAD.dman_rspn_dvcd 필드 없음");
assertEquals("S", item.getValue());
}
@Test
void HEAD_procs_rslt_dvcd_기본값_S() {
StandardItem item = message.findItem("HEAD.procs_rslt_dvcd");
assertNotNull(item, "HEAD.procs_rslt_dvcd 필드 없음");
assertEquals("S", item.getValue());
}
@Test
void HEAD_trnm_sys_dvcd_기본값_EAI() {
StandardItem item = message.findItem("HEAD.trnm_sys_dvcd");
assertNotNull(item, "HEAD.trnm_sys_dvcd 필드 없음");
assertEquals("EAI", item.getValue());
}
// ----------------------------------------------------------------
// MSG 영역 구조 검증
// ----------------------------------------------------------------
@Test
void MSG_MAIN_MSG_블록_존재() {
assertNotNull(message.findItem("MSG.MAIN_MSG"), "MSG.MAIN_MSG 블록 없음");
}
@Test
void MSG_outp_msg_cd_길이12() {
StandardItem item = message.findItem("MSG.MAIN_MSG.outp_msg_cd");
assertNotNull(item, "MSG.MAIN_MSG.outp_msg_cd 필드 없음");
assertEquals(12, item.getLength());
}
@Test
void MSG_msg_list_Grid_존재() {
assertNotNull(message.findItem("MSG.msg_list"), "MSG.msg_list Grid 없음");
}
// ----------------------------------------------------------------
// DATA 영역 구조 검증
// ----------------------------------------------------------------
@Test
void DATA_BIZ_DATA_존재() {
assertNotNull(message.findItem("DATA.BIZ_DATA"), "DATA.BIZ_DATA 없음");
}
// ----------------------------------------------------------------
// setData / findItemValue 기본 동작
// ----------------------------------------------------------------
@Test
void HEAD_필드_setData_findItemValue() {
String guid40 = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; // 40자
message.setData("HEAD.guid", guid40);
assertEquals(guid40, message.findItemValue("HEAD.guid"));
}
@Test
void MSG_필드_setData_findItemValue() {
message.setData("MSG.MAIN_MSG.outp_msg_ctnt", "테스트오류메시지");
assertEquals("테스트오류메시지", message.findItemValue("MSG.MAIN_MSG.outp_msg_ctnt"));
}
}