From a7fde3f81e263e68f0622d28b18c1a61c6ec487a Mon Sep 17 00:00:00 2001 From: curry772 Date: Thu, 3 Sep 2026 08:57:17 +0900 Subject: [PATCH] =?UTF-8?q?=ED=91=9C=EC=A4=80=20=EC=98=A4=EB=A5=98?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=ED=98=95?= =?UTF-8?q?=EC=8B=9D=EC=9D=84=20PropManager=20=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DefaultProcess.setResMsg() 두 곳(표준/준표준 오류응답)에 하드코딩돼 있던 String.format("[%s] %s (%s)", ...) 를 프로퍼티 기반으로 바꾼다. - 그룹/키: DefaultProcess / std.error.msg.format - 인자 순서: 1=오류코드, 2=오류메시지, 3=오류상세 - 기본형식: "[%s] %s" 프로퍼티는 에이전트의 ReloadPropertyCommand 로 무중단 갱신될 수 있으므로 캐시하지 않고 호출할 때마다 조회한다. 방어 두 가지를 함께 넣는다. - 그룹/키가 없거나 값이 공백이면 기본형식을 쓴다. 설정을 넣지 않아도 동작한다. - 형식이 잘못되면(%s 개수 불일치 등) String.format 이 IllegalFormatException 을 던지는데, 하필 오류응답 경로라 여기서 예외가 나면 오류 자체를 못 내려보낸다. 조립 실패 시 경고만 남기고 기본형식으로 되돌린다. 특정 사이트 전용이 아닌 공통 기능이다. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UnybKuxcuPafGhVGh4wqkZ --- .../eactive/eai/outbound/DefaultProcess.java | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/eactive/eai/outbound/DefaultProcess.java b/src/main/java/com/eactive/eai/outbound/DefaultProcess.java index fae5bdd..ce2ce49 100644 --- a/src/main/java/com/eactive/eai/outbound/DefaultProcess.java +++ b/src/main/java/com/eactive/eai/outbound/DefaultProcess.java @@ -20,6 +20,7 @@ import com.eactive.eai.common.header.HeaderActionKeys; import com.eactive.eai.common.message.EAIMessage; import com.eactive.eai.common.message.EAIMessageKeys; import com.eactive.eai.common.message.MessageType; +import com.eactive.eai.common.property.PropManager; import com.eactive.eai.common.routing.Process; import com.eactive.eai.common.server.EAIServerManager; import com.eactive.eai.common.submessage.SubMessageManager; @@ -43,6 +44,12 @@ public abstract class DefaultProcess extends Process { protected static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT); protected static Logger esbLogger = Logger.getLogger(Logger.LOGGER_ESBFW); + /** 표준 오류응답 메시지 형식을 조회할 프로퍼티 그룹/키. 없으면 기본형식을 쓴다. */ + public static final String PROP_GROUP = "DefaultProcess"; + public static final String PROP_STD_ERR_MSG_FORMAT = "std.error.msg.format"; + /** 인자 순서: 1=오류코드, 2=오류메시지, 3=오류상세 */ + public static final String DEFAULT_STD_ERR_MSG_FORMAT = "[%s] %s"; + protected String guidLogPrefix = this.getClass().getSimpleName() + "] "; protected static ThreadLocal local = new ThreadLocal(); // 경과시간 동기화를 위한 ThreadLocal @@ -689,7 +696,7 @@ public abstract class DefaultProcess extends Process { String errorCode = mapper.getErrorCode(resStandardMessage); String errorMsg = StringUtils.trim(mapper.getErrorMsg(resStandardMessage)); String errorDesc = StringUtils.trim(resStandardMessage.findItemValue("MSG.MAIN_MSG.outp_msg_desc")); - this.resEaiMsg.setRspErr("RECEAIINA001", String.format("[%s] %s (%s)", errorCode, errorMsg, errorDesc)); + this.resEaiMsg.setRspErr("RECEAIINA001", formatStdErrorMessage(errorCode, errorMsg, errorDesc)); return; } else { this.resEaiMsg.setRspErr("RECEAIINA001", "비표준 오류 응답 수신"); @@ -707,7 +714,7 @@ public abstract class DefaultProcess extends Process { String errorCode = mapper.getErrorCode(resStandardMessage); String errorMsg = StringUtils.trim(mapper.getErrorMsg(resStandardMessage)); String errorDesc = StringUtils.trim(resStandardMessage.findItemValue("MSG.MAIN_MSG.outp_msg_desc")); - this.resEaiMsg.setRspErr("RECEAIINA001", String.format("[%s] %s (%s)", errorCode, errorMsg, errorDesc)); + this.resEaiMsg.setRspErr("RECEAIINA001", formatStdErrorMessage(errorCode, errorMsg, errorDesc)); } else { this.resEaiMsg.setRspErr("RECEAIINA001", "비표준 오류 응답 수신"); } @@ -720,6 +727,37 @@ public abstract class DefaultProcess extends Process { } } + /** + * 표준 오류응답 메시지를 조립한다. + * + * 형식은 PropManager 의 {@code DefaultProcess / std.error.msg.format} 에서 가져온다. + * 프로퍼티는 에이전트의 ReloadPropertyCommand 로 무중단 갱신될 수 있으므로, + * 캐시하지 않고 호출할 때마다 조회한다. 그룹이나 키가 없으면 + * {@link #DEFAULT_STD_ERR_MSG_FORMAT} 를 쓴다. + * + * 형식 문자열은 운영에서 편집 가능하므로 잘못된 형식(예: %s 개수 불일치)이 들어올 수 있다. + * 이 메서드는 오류응답 경로에서 호출되므로 여기서 예외가 나면 오류 자체를 못 내려보낸다. + * 따라서 조립에 실패하면 경고만 남기고 기본형식으로 되돌린다. + * + * @param errorCode 오류코드 (형식 인자 1) + * @param errorMsg 오류메시지 (형식 인자 2) + * @param errorDesc 오류상세 (형식 인자 3) + */ + protected String formatStdErrorMessage(String errorCode, String errorMsg, String errorDesc) { + String format = PropManager.getInstance().getProperty( + PROP_GROUP, PROP_STD_ERR_MSG_FORMAT, DEFAULT_STD_ERR_MSG_FORMAT); + if (StringUtils.isBlank(format)) { + format = DEFAULT_STD_ERR_MSG_FORMAT; + } + try { + return String.format(format, errorCode, errorMsg, errorDesc); + } catch (Exception e) { + logger.warn(guidLogPrefix + " 표준 오류응답 형식이 잘못되어 기본형식으로 대체한다. [" + + PROP_GROUP + "/" + PROP_STD_ERR_MSG_FORMAT + "=" + format + "] - " + e.getMessage()); + return String.format(DEFAULT_STD_ERR_MSG_FORMAT, errorCode, errorMsg, errorDesc); + } + } + public boolean isTgtTranCall() { return this.isTgtTran; }