diff --git a/src/main/java/com/eactive/eai/MessageKeyTest.java b/src/main/java/com/eactive/eai/MessageKeyTest.java
deleted file mode 100644
index c7f2a12..0000000
--- a/src/main/java/com/eactive/eai/MessageKeyTest.java
+++ /dev/null
@@ -1,380 +0,0 @@
-package com.eactive.eai;
-
-import com.eactive.eai.common.EAITable;
-import com.eactive.eai.common.util.MessageUtil;
-import org.json.simple.JSONValue;
-
-/**
- * 테스트용 메시지 키 검증 클래스
- */
-public class MessageKeyTest {
-
-
- /**
- * XML 또는 JSON 메시지의 성공 여부를 검증하는 테스트용 메소드
- * 추출된 값을 배열로 반환
- */
- public static TestResult isSuccessMessageTest(String messageType, Object message, String path, String expectedValue) {
- try {
- String extractedValue = "";
-
- if(EAITable.XML_TYPE.equals(messageType)) {
- if(message instanceof byte[]) {
- extractedValue = extractXmlValue(new String((byte[])message), path);
- } else if(message instanceof String) {
- extractedValue = extractXmlValue((String)message, path);
- }
- }
- else if(EAITable.JSON_TYPE.equals(messageType)) {
- Object json = JSONValue.parse((String)message);
- extractedValue = extractJsonValue(json, path);
- }
-
- if(extractedValue == null) extractedValue = "";
- boolean result = compareMessageValue(extractedValue, expectedValue);
-
- return new TestResult(result, extractedValue);
-
- } catch(Exception e) {
- e.printStackTrace();
- return new TestResult(false, "오류 발생: " + e.getMessage());
- }
- }
-
- // 테스트 결과를 담는 클래스
- static class TestResult {
- boolean success;
- String extractedValue;
-
- TestResult(boolean success, String extractedValue) {
- this.success = success;
- this.extractedValue = extractedValue;
- }
- }
-
- /**
- * 메시지 값 비교를 수행하는 메소드
- */
- private static boolean compareMessageValue(String actualValue, String expectedValue) {
- if(actualValue == null) actualValue = "";
- if(expectedValue == null) return false;
-
- // 예약어로 시작하는 경우
- if(expectedValue.startsWith("@")) {
- return compareWithReservedWord(actualValue, expectedValue);
- }
-
- // 일반 equals 비교
- return actualValue.equals(expectedValue);
- }
-
- /**
- * 예약어를 포함한 값 비교 처리
- */
- private static boolean compareWithReservedWord(String actualValue, String definition) {
- if (actualValue == null) actualValue = "";
- if (definition == null) return false;
-
- try {
- // 1. 기본 비교
- if (definition.startsWith("@eq:")) {
- return actualValue.equals(definition.substring(4));
- }
- if (definition.startsWith("@ne:")) {
- return !actualValue.equals(definition.substring(4));
- }
- if ("@null".equals(definition)) {
- return actualValue.isEmpty();
- }
- if ("@!null".equals(definition)) {
- return !actualValue.isEmpty();
- }
-
- // 2. 문자열 패턴
- if (definition.startsWith("@contains:")) {
- String[] values = definition.substring(10).split(",");
- for (String value : values) {
- if (actualValue.equals(value.trim())) {
- return true;
- }
- }
- return false;
- }
- if (definition.startsWith("@!contains:")) {
- String[] values = definition.substring(11).split(",");
- for (String value : values) {
- if (actualValue.equals(value.trim())) {
- return false;
- }
- }
- return true;
- }
- if (definition.startsWith("@starts:")) {
- return actualValue.startsWith(definition.substring(8));
- }
- if (definition.startsWith("@ends:")) {
- return actualValue.endsWith(definition.substring(6));
- }
-
- // 3. 숫자 비교
- if (definition.startsWith("@gt:") ||
- definition.startsWith("@lt:") ||
- definition.startsWith("@ge:") ||
- definition.startsWith("@le:")) {
-
- double actualNum = Double.parseDouble(actualValue);
- if (definition.startsWith("@gt:")) {
- double defNum = Double.parseDouble(definition.substring(4));
- return actualNum > defNum;
- }
- if (definition.startsWith("@lt:")) {
- double defNum = Double.parseDouble(definition.substring(4));
- return actualNum < defNum;
- }
- if (definition.startsWith("@ge:")) {
- double defNum = Double.parseDouble(definition.substring(4));
- return actualNum >= defNum;
- }
- if (definition.startsWith("@le:")) {
- double defNum = Double.parseDouble(definition.substring(4));
- return actualNum <= defNum;
- }
- }
-
- return false;
- } catch (Exception e) {
- return false;
- }
- }
-
- /**
- * XML 값 추출 메소드
- */
- private static String extractXmlValue(String xmlMessage, String path) {
- if(path == null) return "";
-
- // XPath 형식인 경우
- if(path.startsWith("//") || path.startsWith("/")) {
- return MessageUtil.getXmlFldByXPath(xmlMessage, path);
- }
-
- // 단순 태그명인 경우
- return MessageUtil.getXmlFld(xmlMessage, path);
- }
-
- /**
- * JSON 값 추출 메소드
- */
- private static String extractJsonValue(Object json, String path) {
- if(path == null) return "";
-
- // JSONPath 형식인 경우
- if(path.startsWith("$.")) {
- return MessageUtil.getJSONValueByPath(json, path);
- }
-
- // 단순 키인 경우
- return MessageUtil.getJSONValue(json, path);
- }
-
- private static void testXml() {
- // System.out.println("\n=== XML 테스트 ===");
-
- // 단순 경로 테스트
- String xml1 = "SUCCESS";
- test("XML 단순 경로",
- EAITable.XML_TYPE,
- xml1,
- "status",
- "SUCCESS");
-
- // 중첩 경로 테스트 (일반 방식)
- String xml2 = "";
- test("XML 중첩 경로 (일반)",
- EAITable.XML_TYPE,
- xml2,
- "resultCode",
- "0000");
-
- // 중첩 경로 테스트 (XPath 방식)
- test("XML 중첩 경로 (XPath)",
- EAITable.XML_TYPE,
- xml2,
- "//response/header/resultCode",
- "0000");
-
- // 네임스페이스가 있는 XML
- String xml3 = "OK";
- test("XML 네임스페이스",
- EAITable.XML_TYPE,
- xml3,
- "//ns:status",
- "OK");
-
- // 실패 케이스
- test("XML 실패 케이스",
- EAITable.XML_TYPE,
- xml1,
- "status",
- "FAIL");
-
- // 존재하지 않는 경로
- test("XML 없는 경로",
- EAITable.XML_TYPE,
- xml1,
- "nonexistent",
- "SUCCESS");
- }
-
- private static void testJson() {
- // System.out.println("\n=== JSON 테스트 ===");
-
- // 단순 경로 테스트
- String json1 = "{\"status\":\"success\"}";
- test("JSON 단순 경로",
- EAITable.JSON_TYPE,
- json1,
- "status",
- "success");
-
- // 중첩 경로 테스트 (일반 방식)
- String json2 = "{\"response\":{\"header\":{\"resultCode\":\"0000\"}}}";
- test("JSON 중첩 경로 (일반)",
- EAITable.JSON_TYPE,
- json2,
- "resultCode",
- "0000");
-
- // 중첩 경로 테스트 (JSONPath 방식)
- test("JSON 중첩 경로 (JSONPath)",
- EAITable.JSON_TYPE,
- json2,
- "$.response.header.resultCode",
- "0000");
-
- // 배열이 포함된 JSON
- String json3 = "{\"responses\":[{\"status\":\"success\"},{\"status\":\"pending\"}]}";
- test("JSON 배열 경로",
- EAITable.JSON_TYPE,
- json3,
- "$.responses[0].status",
- "success");
-
- // 실패 케이스
- test("JSON 실패 케이스",
- EAITable.JSON_TYPE,
- json1,
- "status",
- "failure");
-
- // 존재하지 않는 경로
- test("JSON 없는 경로",
- EAITable.JSON_TYPE,
- json1,
- "nonexistent",
- "success");
- }
-
- public static void main(String[] args) {
- testXml();
- testJson();
- testReservedWords();
- }
-
- private static void testReservedWords() {
- // System.out.println("\n=== 예약어 테스트 ===");
-
- // 1. 기본 비교 테스트
- test("예약어 - eq",
- EAITable.XML_TYPE,
- "SUCCESS",
- "code",
- "@eq:SUCCESS");
-
- test("예약어 - ne",
- EAITable.XML_TYPE,
- "SUCCESS",
- "code",
- "@ne:FAIL");
-
- test("예약어 - null",
- EAITable.XML_TYPE,
- "",
- "code",
- "@null");
-
- test("예약어 - !null",
- EAITable.XML_TYPE,
- "SUCCESS",
- "code",
- "@!null");
-
- // 2. 문자열 패턴 테스트
- test("예약어 - contains",
- EAITable.JSON_TYPE,
- "{\"status\":\"success\"}",
- "status",
- "@contains:success,ok,done");
-
- test("예약어 - !contains",
- EAITable.JSON_TYPE,
- "{\"status\":\"success\"}",
- "status",
- "@!contains:fail,error,invalid");
-
- test("예약어 - starts",
- EAITable.JSON_TYPE,
- "{\"code\":\"SUCCESS_001\"}",
- "code",
- "@starts:SUCCESS");
-
- test("예약어 - ends",
- EAITable.JSON_TYPE,
- "{\"code\":\"ERR_001\"}",
- "code",
- "@ends:001");
-
- // 3. 숫자 비교 테스트
- test("예약어 - gt",
- EAITable.JSON_TYPE,
- "{\"value\":\"100\"}",
- "value",
- "@gt:50");
-
- test("예약어 - lt",
- EAITable.JSON_TYPE,
- "{\"value\":\"100\"}",
- "value",
- "@lt:150");
-
- test("예약어 - ge",
- EAITable.JSON_TYPE,
- "{\"value\":\"100\"}",
- "value",
- "@ge:100");
-
- test("예약어 - le",
- EAITable.JSON_TYPE,
- "{\"value\":\"100\"}",
- "value",
- "@le:100");
-
- // 4. 실패 케이스
- test("예약어 - 잘못된 숫자",
- EAITable.JSON_TYPE,
- "{\"value\":\"invalid\"}",
- "value",
- "@gt:50");
-
- test("예약어 - 잘못된 패턴",
- EAITable.JSON_TYPE,
- "{\"status\":\"success\"}",
- "status",
- "@invalid:pattern");
- }
-
- private static void test(String testName, String type, String message, String path, String expected) {
- TestResult result = isSuccessMessageTest(type, message, path, expected);
- // System.out.println(String.format( "테스트: %s\n결과: %s\n메시지: %s\n경로: %s\n기대값: %s\n추출된 값: [%s]\n",testName, result.success ? "성공" : "실패",message,path,expected,result.extractedValue ));
- }
-}
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/adapter/controller/ApiRequestBodyFilter.java b/src/main/java/com/eactive/eai/adapter/controller/ApiRequestBodyFilter.java
index d557e84..ab9d793 100644
--- a/src/main/java/com/eactive/eai/adapter/controller/ApiRequestBodyFilter.java
+++ b/src/main/java/com/eactive/eai/adapter/controller/ApiRequestBodyFilter.java
@@ -21,6 +21,9 @@ import com.eactive.eai.adapter.http.dynamic.HttpDynamicInAdapterManager;
import com.eactive.eai.adapter.http.dynamic.HttpDynamicInAdapterUri;
import com.eactive.eai.common.stdmessage.STDMessageManager;
import com.eactive.eai.common.stdmessage.STDMsgInfoAddOnVO;
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
public class ApiRequestBodyFilter extends OncePerRequestFilter {
@@ -32,17 +35,12 @@ public class ApiRequestBodyFilter extends OncePerRequestFilter {
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
-
+ System.out.println("ApiRequestBodyFilter : " + request.getRequestURI());
if (!isTarget(request)) {
filterChain.doFilter(request, response);
return;
}
-
- String encoding = getInboundGroupAdapterEncoding(request);
-
-
-
//원본 바디를 byte[]로 읽기 (개행 포함 그대로) 왜? 뒤에 필터에서 HMAC값 계산할수도 있어서 변조되면 안됨. 개행문자도 그대로 가야함.
byte[] rawBody = readBodyAsBytes(request);
@@ -54,14 +52,16 @@ public class ApiRequestBodyFilter extends OncePerRequestFilter {
byte[] finalBody = rawBody;
try {
+ if(isJsonArray(rawBody)) {
+ String encoding = getInboundGroupAdapterEncoding(request);
+ String bodyStr = new String(rawBody, encoding);
+ Object json = JSONValue.parse(bodyStr);
- String bodyStr = new String(rawBody, encoding);
- Object json = JSONValue.parse(bodyStr);
-
- if (json instanceof JSONArray) {
- bodyStr = DJB_ROOTLESS_ARRAY + bodyStr + "}";
- finalBody = bodyStr.getBytes(encoding);
- }
+ if (json instanceof JSONArray) {
+ bodyStr = DJB_ROOTLESS_ARRAY + bodyStr + "}";
+ finalBody = bodyStr.getBytes(encoding);
+ }
+ }
} catch (Exception e) {
// JSON 파싱 실패 시 원본 유지
@@ -74,6 +74,14 @@ public class ApiRequestBodyFilter extends OncePerRequestFilter {
filterChain.doFilter(wrapped, response);
}
+
+ public static boolean isJsonArray(byte[] json) {
+ try (JsonParser parser = new JsonFactory().createParser(json)) {
+ return parser.nextToken() == JsonToken.START_ARRAY;
+ } catch (Exception e) {
+ return false;
+ }
+ }
private boolean isTarget(HttpServletRequest request) {
String uri = request.getRequestURI();
diff --git a/src/main/java/com/eactive/eai/adapter/controller/DJErpApiAdapterController.java b/src/main/java/com/eactive/eai/adapter/controller/DJErpApiAdapterController.java
index a8cb361..c5a464a 100644
--- a/src/main/java/com/eactive/eai/adapter/controller/DJErpApiAdapterController.java
+++ b/src/main/java/com/eactive/eai/adapter/controller/DJErpApiAdapterController.java
@@ -112,105 +112,35 @@ public class DJErpApiAdapterController implements HttpAdapterServiceKey {
MediaType mediaType = MediaType.valueOf("application/json;charset=" + encode);
String errorResponseFormat = httpProp.getProperty(ERROR_RESPONSE_FORMAT);
- String responseType = httpProp.getProperty(RESPONSE_TYPE, "SYNC");
- ResponseEntity responseEntity = null;
+ ResponseEntity responseEntity = null;
Properties transactionProp = new Properties();
String uuid = UUIDGenerator.getUUID().toString().replaceAll("-", "");
transactionProp.setProperty(TransactionContextKeys.TRANSACTION_UUID, uuid);
MDC.put(Logger.DISCRIMINATOR, transactionProp.getProperty(TransactionContextKeys.TRANSACTION_UUID));
+
// jwhong, put api received time, eaiSvcCode
transactionProp.put(INBOUND_REQUESTED_TIME, receivedTimeStr);
-
- // ** jwhong TSEAIHS04의 api full path와 비교하여 adapter를 가져온다
-// String bzwkSvcKeyName = ""; // Adapter Group별 Action Class에 따라 구성이 달라짐. 예)
-// // _AGW_IN_RST_SyS:POST/account/{acc_no}
-// String adapterGrpName = ""; // Adapter Group명 예) _AGW_IN_RST_SyS : API_PATH(/api/test)
- String apiSvcCode = ""; // eaiSvcCd 예) LONNCHCON00005S2
- String apiFullPathKey = ""; // 예) POST|/api/test/account/list, POST|/api/test/account/{acc_no}
- Map pathVariables = null;
- try {
- // PathVariable(ex:/api/test/account/{acc_no}) 대응 및 DAO조회 제거.
- // /api/test/account/1234567 호출시 /api/test/account/{acc_no} API 로 식별.
-
-// String methodAndUri = getRequestRuledPath(servletRequest, apiUri, adapterVO, transactionProp);
- String methodAndUri = servletRequest.getMethod() + "|" + apiUri;
- STDMessageManager manager = STDMessageManager.getInstance();
- STDMsgInfoAddOnVO stdMsgInfo = manager.getStdMsgInfoAddOn(methodAndUri);
-// bzwkSvcKeyName = stdMsgInfo.getBzwksvckeyname();
- apiSvcCode = stdMsgInfo.getEaiSvcCd();
- transactionProp.put(API_SERVICE_CODE, apiSvcCode);
-
-// adapterGrpName = stdMsgInfo.gAdapterGroupName();
- apiFullPathKey = stdMsgInfo.getApiFullPath();
- if (STDMessageManager.isPathVariable(apiFullPathKey)) {
- pathVariables = new AntPathMatcher().extractUriTemplateVariables(apiFullPathKey, methodAndUri);
- }
-
-// adptUri = findAdptUri(apiUri, HttpDynamicInAdapterManager.getInstance(), adapterGrpName);
- } catch (Exception e) {
-// adptUri = null;
- }
- // ***
- if (pathVariables != null) {
- transactionProp.put(INBOUND_PATH_VARIABLES, pathVariables);
- }
String responseData = "";
try {
responseData = service.callApi(servletRequest, servletResponse, httpProp, adapterGroupVO, adapterVO,
transactionProp);
- // if (RESPONSE_TYPE_ASYNC.equals(responseType)) { // table의 값이 ASYNC 로 들어가 있는데
- // response_type_async는 ASYN 로 되어 있어 아래처럼 비교함 jwhong 2025
- if ("ASYNC".equals(responseType)) {
- // responseEntity = ResponseEntity.ok("dummy"); // comment by jwhong
- // servletResponse.addHeader("traceId", responseData); // uuid를 response header에
- servletResponse.addHeader("traceId",
- transactionProp.getProperty(TransactionContextKeys.TRANSACTION_UUID)); // uuid를 response header에
- int httpStatus = servletResponse.getStatus();
- if (httpStatus == 200) {
- // 업체별 aync response message 가 다르다.
- String asyncMsgStyle = httpProp.getProperty("ASYNC_RTNMSG_TYPE", "");
- String responseBody = "";
- boolean encryptAsyncAckApply = StringUtils
- .equalsIgnoreCase(httpProp.getProperty("ASYNC_ENCRYPT_ACK", "N"), "Y");
- if (asyncMsgStyle == null || asyncMsgStyle.trim().isEmpty()) {
- responseBody = makeResponseBodyMsg();
- } else {
- responseBody = asyncMsgStyle;
- }
- if (encryptAsyncAckApply) {
- responseBody = service.doPostEncryption(responseBody, transactionProp, servletRequest);
- }
-
- responseEntity = ResponseEntity.status(httpStatus).contentType(mediaType).body(responseBody);
- // jwhong
- } else {
- responseEntity = ResponseEntity.status(httpStatus).contentType(mediaType).body(responseData);
- }
+ servletResponse.addHeader("traceId",
+ transactionProp.getProperty(TransactionContextKeys.TRANSACTION_UUID)); // uuid를 response header에
+ int httpStatus = servletResponse.getStatus();
+ if (httpStatus != 200) {
+ responseEntity = ResponseEntity.status(httpStatus).contentType(mediaType).body(responseData);
} else {
-// responseEntity = ResponseEntity.ok().contentType(mediaType).body(responseData);
-// 버즈빌 포인트 적립 처리하기 위하여 정상응답이더라도 응답코드(apiRsltCd) 값이 200이 아닌 경우 처리를 위하여 수정
-// Filter에서 설정한 response status값을 responseEntity 생성시 적용 modify by lwk 2025.03.24
-
- servletResponse.addHeader("traceId",
- transactionProp.getProperty(TransactionContextKeys.TRANSACTION_UUID)); // uuid를 response header에
- int httpStatus = servletResponse.getStatus();
- if (httpStatus != 200) {
- responseEntity = ResponseEntity.status(httpStatus).contentType(mediaType).body(responseData);
- } else {
- responseEntity = ResponseEntity.ok().contentType(mediaType).body(responseData);
- }
+ responseEntity = ResponseEntity.ok().contentType(mediaType).body(responseData);
}
} catch (Exception e) {
-
-
logger.error(adapterGroupName + "-" + adapterName + ">>" + e.getMessage(), e);
String errorMsg = null;
- if( e instanceof HttpStatusException ) {
+ if(e instanceof HttpStatusException ) {
logger.warn("ApiAdapterController] " + adapterGroupName + "-" + adapterName + ">>" + e.getMessage());
HttpStatusException e1 = (HttpStatusException) e;
errorMsg = MessageUtil.makeErrorMessageByMessageType(adptMsgType, encode,
@@ -232,13 +162,6 @@ public class DJErpApiAdapterController implements HttpAdapterServiceKey {
responseEntity = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).contentType(mediaType)
.body(errorMsg);
}
- String postFilterNames = httpProp.getProperty("POST_FILTERS","");
-
- if( postFilterNames.contains("HMAC_SHA256") ) {
- HttpAdapterFilter filter = HttpAdapterFilterFactory.createFilter("HMAC_SHA256");
- filter.doPostFilter(adapterGroupName, postFilterNames, errorMsg, transactionProp, servletRequest, servletResponse);
- }
-
responseData = errorMsg;
} finally {
@@ -252,22 +175,6 @@ public class DJErpApiAdapterController implements HttpAdapterServiceKey {
servletRequest.setAttribute(TransactionContextKeys.TRANSACTION_PROP, transactionProp);
- if (!"ASYNC".equals(responseType)) {
-// String uuid = transactionProp.getProperty(TransactionContextKeys.TRANSACTION_UUID);
- String url = transactionProp.getProperty(HttpClientAdapterServiceKey.INBOUND_EXTURI);
- String method = transactionProp.getProperty(HttpClientAdapterServiceKey.INBOUND_METHOD);
- int httpStatusCode = servletResponse.getStatus();
-
- Map