Files
eapim-online/src/main/java/com/eactive/eai/adapter/controller/DJBApiAdapterController.java
T

357 lines
16 KiB
Java

package com.eactive.eai.adapter.controller;
import java.util.Date;
import java.util.Map;
import java.util.Properties;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.eactive.eai.adapter.AdapterGroupVO;
import com.eactive.eai.adapter.AdapterManager;
import com.eactive.eai.adapter.AdapterPropManager;
import com.eactive.eai.adapter.AdapterVO;
import com.eactive.eai.adapter.handler.AdapterErrorMessageHandler;
import com.eactive.eai.adapter.handler.AdapterErrorMessageHandlerFactory;
import com.eactive.eai.adapter.http.HttpStatusException;
import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceKey;
import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceSupport;
import com.eactive.eai.adapter.http.dynamic.HttpDynamicInAdapterManager;
import com.eactive.eai.adapter.http.dynamic.HttpDynamicInAdapterUri;
import com.eactive.eai.adapter.http.dynamic.filter.FilterException;
import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthException;
import com.eactive.eai.adapter.service.DJBApiAdapterService;
import com.eactive.eai.common.TransactionContextKeys;
import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.server.EAIServerManager;
import com.eactive.eai.common.util.DatetimeUtil;
import com.eactive.eai.common.util.HttpAdapterExtraLogUtil;
import com.eactive.eai.common.util.InboundErrorLogger;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.common.util.MessageUtil;
import com.eactive.eai.common.util.RestSendBodyLogUtils;
import com.eactive.eai.common.util.TxFileLogger;
import com.eactive.eai.common.util.TxSiftContext;
import com.eactive.eai.common.util.UUIDGenerator;
import com.eactive.eai.inbound.error.InboundErrorInfoVO;
import com.eactive.eai.util.HexaConverter;
@RestController
public class DJBApiAdapterController implements HttpAdapterServiceKey {
static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
@Autowired
DJBApiAdapterService service;
/**
* DJErp OAuth 조기 적용을 위한 Controller
*
* @See com.eactive.eai.authserver.config.AuthorizationServerConfig.configure(AuthorizationServerEndpointsConfigurer
* endpoints)
*/
@RequestMapping(value = {
"/dj/{path:^(?!oauth).*$}", "/dj/{path:^(?!oauth).*$}/**",
"/kp/{path:^(?!oauth).*$}", "/kp/{path:^(?!oauth).*$}/**",
"/kkb/{path:^(?!oauth).*$}", "/kkb/{path:^(?!oauth).*$}/**",
"/nf/{path:^(?!oauth).*$}", "/nf/{path:^(?!oauth).*$}/**",
"/bsd/{path:^(?!oauth).*$}", "/bsd/{path:^(?!oauth).*$}/**",
"/tss/{path:^(?!oauth).*$}", "/tss/{path:^(?!oauth).*$}/**",
"/tsb/{path:^(?!oauth).*$}", "/tsb/{path:^(?!oauth).*$}/**",
"/shb/{path:^(?!oauth).*$}", "/shb/{path:^(?!oauth).*$}/**",
"/tst/{path:^(?!oauth).*$}", "/tst/{path:^(?!oauth).*$}/**",
"/**/{path:^(?!oauth)(?!favicon\\.ico$).*$}", "/**/{path:^(?!oauth)(?!favicon\\.ico$).*$}/**",
})
public ResponseEntity<String> callApi(HttpServletRequest servletRequest, HttpServletResponse servletResponse)
throws Exception {
// /ONLWeb/api/v1/public/getUserInfo.svc
String apiUri = servletRequest.getRequestURI();
// /api/v1/public/getUserInfo.svc
apiUri = StringUtils.removeStart(apiUri, servletRequest.getContextPath());
apiUri = StringUtils.removeEnd(apiUri, "/");
HttpDynamicInAdapterUri adptUri = findAdptUri(apiUri, HttpDynamicInAdapterManager.getInstance(), "");
if (logger.isDebug()) {
logger.debug("ApiAdapterController] service request uri : " + servletRequest.getRequestURI());
}
// Received time , jwhong
long receivedTimeMillis = System.currentTimeMillis(); // 밀리세컨 단위로 보내야함
String receivedTimeStr = String.valueOf(receivedTimeMillis);
ResponseEntity<String> responseEntity = null;
Properties transactionProp = new Properties();
String uuid = UUIDGenerator.getUUID().toString().replaceAll("-", "");
transactionProp.setProperty(TransactionContextKeys.TRANSACTION_UUID, uuid);
transactionProp.put(INBOUND_REQUESTED_TIME, receivedTimeStr);
if (adptUri == null) {
//logError(servletRequest);
String errorMsg = MessageUtil.makeJsonErrorMessage(MessageUtil.ERROR_CODE_SERVICE_NOT_FOUND,
"can not find Adapter Uri");
logError(servletRequest, "HTTP_IN_NO_URI", MessageUtil.ERROR_CODE_SERVICE_NOT_FOUND,
errorMsg, transactionProp, null);
return ResponseEntity.status(HttpStatus.NOT_FOUND).contentType(MediaType.APPLICATION_JSON).body(errorMsg);
}
String adapterGroupName = adptUri.getAdptGrpName();
String adapterName = adptUri.getAdptName();
AdapterGroupVO adapterGroupVO = AdapterManager.getInstance().getAdapterGroupVO(adapterGroupName);
AdapterVO adapterVO = AdapterManager.getInstance().getAdapterVO(adapterGroupName, adapterName);
if (adapterVO == null) {
String errorMsg = MessageUtil.makeJsonErrorMessage(MessageUtil.ERROR_CODE_AP_ERROR,
"Adapter not found error");
logError(servletRequest, adapterGroupName, MessageUtil.ERROR_CODE_AP_ERROR,
errorMsg, transactionProp, null);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).contentType(MediaType.APPLICATION_JSON)
.body(errorMsg);
}
Properties httpProp = AdapterPropManager.getInstance().getProperties(adapterVO.getPropGroupName());
String adptMsgType = adapterVO.getAdapterGroupVO().getMessageType();
String encode = StringUtils.defaultIfBlank(adapterGroupVO.getMessageEncode(), "UTF-8");
MediaType mediaType = MediaType.valueOf("application/json;charset=" + encode);
String errorResponseFormat = httpProp.getProperty(ERROR_RESPONSE_FORMAT);
TxSiftContext.begin(uuid);
// jwhong, put api received time, eaiSvcCode
String responseData = "";
try {
responseData = service.callApi(servletRequest, servletResponse, httpProp, adapterGroupVO, adapterVO,
transactionProp);
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);
}
} catch (Exception e) {
logger.error(adapterGroupName + "-" + adapterName + ">>" + e.getMessage(), e);
String responseErrorMsg = null;
if (e instanceof FilterException) {
responseErrorMsg = genErrorResponseMessage(adapterGroupName, adapterName,
transactionProp, MessageUtil.ERROR_CODE_AP_ERROR, e, adptMsgType, encode, errorResponseFormat);
FilterException e1 = (FilterException) e;
this.logError(servletRequest, adapterGroupName, e1.getCode(), responseErrorMsg, transactionProp, e);
logger.error("ApiAdapterController] " + adapterGroupName + "-" + adapterName + ">>" + e.getMessage());
responseEntity = ResponseEntity.status(e1.getStatus()).contentType(mediaType).body(responseErrorMsg);
} else if (e instanceof JwtAuthException) {
responseErrorMsg = genErrorResponseMessage(adapterGroupName, adapterName,
transactionProp, MessageUtil.ERROR_CODE_AP_ERROR, e, adptMsgType, encode, errorResponseFormat);
JwtAuthException e1 = (JwtAuthException) e;
this.logError(servletRequest, adapterGroupName, e1.getCode(), responseErrorMsg, transactionProp, e);
logger.error("ApiAdapterController] " + adapterGroupName + "-" + adapterName + ">>" + e.getMessage(), e);
responseEntity = ResponseEntity.status(HttpStatus.UNAUTHORIZED).contentType(mediaType).body(responseErrorMsg);
} else if (e instanceof HttpStatusException) {
responseErrorMsg = genErrorResponseMessage(adapterGroupName, adapterName,
transactionProp, MessageUtil.ERROR_CODE_AUTH_FAIL, e, adptMsgType, encode, errorResponseFormat);
logger.error("ApiAdapterController] " + adapterGroupName + "-" + adapterName + ">>" + e.getMessage());
HttpStatusException e1 = (HttpStatusException) e;
responseEntity = ResponseEntity.status(e1.getStatus()).contentType(mediaType).body(responseErrorMsg);
} else {
responseErrorMsg = genErrorResponseMessage(adapterGroupName, adapterName,
transactionProp, MessageUtil.ERROR_CODE_AP_ERROR, e, adptMsgType, encode, errorResponseFormat);
this.logError(servletRequest, adapterGroupName, MessageUtil.ERROR_CODE_AP_ERROR, responseErrorMsg, transactionProp, e);
logger.error(adapterGroupName + "-" + adapterName + ">>" + e.getMessage(), e);
responseEntity = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).contentType(mediaType).body(responseErrorMsg);
}
responseData = responseErrorMsg;
} finally {
// 어댑터 HTTP 로그에 응답 body 출력
if (RestSendBodyLogUtils.isBodyLoggingApi(transactionProp.getProperty("API_SERVICE_CODE"))) {
String trimmedBody = RestSendBodyLogUtils.getBodyByMaxSize(responseData);
transactionProp.setProperty(HttpAdapterExtraLogUtil.BODY_FIELD_NAME, trimmedBody);
}
servletRequest.setAttribute(TransactionContextKeys.TRANSACTION_PROP, transactionProp);
/**
* 로깅 인터셉터에 데이터를 전달하기 위한 처리 이미 거래처리가 끝나서 영향도가 없을만한 servletRequest에 Attribute로 전달
* 추후 더 좋은방법이 생길경우 개선 요망
*/
try {
TxFileLogger.logTxFile(transactionProp, responseData, "[IN_SEND]");
servletRequest.setAttribute(TransactionContextKeys.TRANSACTION_PROP, transactionProp);
} catch (Exception e) {
logger.warn("http header db logging fail.", e);
} finally {
TxSiftContext.end();
}
}
return responseEntity;
}
private String genErrorResponseMessage(String adapterGroupName, String adapterName,
Properties callProp, String code, Throwable e, String adptMsgType, String encode, String errorResponseFormat) {
String errorHandlerClass = AdapterPropManager.getInstance().getProperty(adapterName, "ERR_MSG_HANDLER");
if (StringUtils.isNotBlank(errorHandlerClass)) {
if (logger.isInfo())
logger.info("ExceptionHandler] errorSyncSend ERR_MSG_HANDLER=" + errorHandlerClass);
AdapterErrorMessageHandler handler = AdapterErrorMessageHandlerFactory.createHandler(errorHandlerClass);
if (handler != null) {
Object resposne;
try {
callProp.put("INBOUND_RESULT_CODE", code);
resposne = handler.generateNonStandardInboundErrorResponseMessage(adapterGroupName, adapterName,
callProp, null, null, e);
return (String)resposne;
} catch (Exception e1) {
logger.warn("AdapterErrorMessageHandler error.", e);
// handler 실패시 아래에서 처리한
}
}
}
return MessageUtil.makeErrorMessageByMessageType(adptMsgType, encode,
code, e.getMessage(), errorResponseFormat);
}
/**
* url에서 뒤쪽 /이후를 제거하면서 찾는다.<br>
* /api/v1/public/getUserInfo.svc
*
* @param apiUri
* @return
*/
private HttpDynamicInAdapterUri findAdptUri(String apiUri, HttpDynamicInAdapterManager manager,
String adapterGrpName) throws Exception {
if (StringUtils.isBlank(apiUri)) {
return null;
}
if(logger.isDebug()) {
logger.debug("===== adptUriMap 상세 내용 =====");
for (Map.Entry<String, HttpDynamicInAdapterUri> entry : manager.adptUriMap.entrySet()) {
HttpDynamicInAdapterUri uriObj = entry.getValue();
logger.debug("GroupName=" + uriObj.getAdptGrpName() + ", AdapterName=" + uriObj.getAdptName() + ", URI="
+ uriObj.getUri());
}
logger.debug("================================");
}
//
for (int i = 0; i < 10; i++) {
HttpDynamicInAdapterUri adptUri = manager.getAdptUri(apiUri);
if (adptUri != null) {
if (StringUtils.isNotEmpty(adapterGrpName)) {
if(adptUri.getAdptGrpName().equals(adapterGrpName)) {
return adptUri;
}
} else {
return adptUri;
}
}
// /api/v1/public
apiUri = StringUtils.substringBeforeLast(apiUri, "/");
if (apiUri.length() < 3) { // /api
return null;
}
}
return null;
}
private void logError(HttpServletRequest request) {
try {
String errorCode = "RECEAIIRP010";
String[] msgArgs = new String[1];
msgArgs[0] = request.getRequestURI();
this.logError(request, "HTTP_IN_NO_URI", errorCode,
ExceptionUtil.make(new Exception("cat not find uri"), errorCode, msgArgs), null, null);
} catch (Throwable t) {
logger.warn("inbound logging failed", t);
}
}
private void logError(HttpServletRequest request, String adapterGroupName, String errorCode,
String errorMsg, Properties prop, Exception e) {
try {
EAIServerManager eaiServerManager = EAIServerManager.getInstance();
String serverName = eaiServerManager.getLocalServerName();
InboundErrorInfoVO errorInfoVO = new InboundErrorInfoVO();
String txId = prop.getProperty(TransactionContextKeys.TRANSACTION_UUID);
if (StringUtils.isEmpty(txId)) {
String instanceid1 = serverName.substring(0, 2);
String instanceid2 = serverName.substring(serverName.length() - 2, serverName.length());
String instid = instanceid1 + instanceid2;
txId = instid + UUIDGenerator.getUUID();
}
errorInfoVO.setEaiSvcSno(txId); // EAI서비스일련번호
errorInfoVO.setAdptBwkGrpNm(adapterGroupName); // 어댑터업무그룹명
errorInfoVO.setErrCd(errorCode); // 에러코드
errorInfoVO.setErrTxt(errorMsg); // 에러내용
errorInfoVO.setErrTm(DatetimeUtil.getCurrentTime(new Date().getTime())); // 에러발생시각
errorInfoVO.setErrDstcd(" ");
StringBuffer sb = new StringBuffer();
String clientId = prop.getProperty(HttpAdapterServiceSupport.PROPERTIES_NAME_CLIENT_ID);
String hexClientId = clientId != null ? HexaConverter.bytesToHexa(clientId.getBytes()) : "";
sb.append(errorMsg).append("\n").append("Remote Addr : ").append(request.getRemoteAddr()).append("\n")
.append("Request URI : ").append(request.getRequestURI()).append("\n").append("clientId=")
.append(clientId).append(",hexClientId=").append(hexClientId).append(",txProp=").append(prop)
.append("\n");
if (e != null)
sb.append("Exception : ").append(e.getMessage());
errorInfoVO.setBwkDataTxt(sb.toString()); // 업무데이터내용
errorInfoVO.setEaiSvrInstNm(serverName); // EAI서버인스턴스명
InboundErrorLogger.error(errorInfoVO);
} catch (Throwable t) {
logger.warn("inbound logging failed", t);
}
}
// private String makeResponseBodyMsg() {
//
// Map<String, Object> dataMap = new HashMap<>();
// dataMap.put("result", 1);
// Map<String, Object> map = new HashMap<>();
//
// map.put("code", "200");
// map.put("data", dataMap);
// map.put("message", "정상 처리 되었습니다.");
//
// JSONObject json = new JSONObject();
// json.putAll(map);
//
// return json.toJSONString();
// }
/*
* private String makeResponseBodyMsg(String asyncMsgStyle) {
*
* Map<String, Object> dataMap = new HashMap<>(); dataMap.put("result", 1);
* Map<String, Object> map = new HashMap<>();
*
* switch (asyncMsgStyle) { case "TB_SUC": map.put("rspCode", "TB_SUC_000");
* map.put("rspMsg", "정상"); map.put("data", dataMap); break; case "ONLYDATA":
* map.put("data", dataMap); map.put("success", "true"); break; default:
* map.put("code", "200"); map.put("data", dataMap); map.put("message",
* "정상 처리 되었습니다."); break; }
*
* JSONObject json = new JSONObject(); json.putAll(map);
*
* return json.toJSONString(); }
*/
}