From 5df860b4c16cebded6d977a7efdb71353b94b1d1 Mon Sep 17 00:00:00 2001 From: Rinjae Date: Thu, 15 Jan 2026 15:21:00 +0900 Subject: [PATCH] =?UTF-8?q?KjbProperty=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ext/kjb/common/KjbPropertyHolder.java | 92 +++++++++++ .../com/eactive/ext/kjb/obp/KjbObpModule.java | 52 +++--- .../com/eactive/ext/kjb/obp/ObpClient.java | 90 +++++------ .../com/eactive/ext/kjb/sso/KjbSsoModule.java | 137 ++++++++-------- .../ext/kjb/ums/KjbEmailSendModule.java | 51 +++--- .../eactive/ext/kjb/ums/KjbUmsService.java | 149 +++++++++--------- 6 files changed, 325 insertions(+), 246 deletions(-) create mode 100644 src/main/java/com/eactive/ext/kjb/common/KjbPropertyHolder.java diff --git a/src/main/java/com/eactive/ext/kjb/common/KjbPropertyHolder.java b/src/main/java/com/eactive/ext/kjb/common/KjbPropertyHolder.java new file mode 100644 index 0000000..16acbd5 --- /dev/null +++ b/src/main/java/com/eactive/ext/kjb/common/KjbPropertyHolder.java @@ -0,0 +1,92 @@ +package com.eactive.ext.kjb.common; + +import lombok.extern.slf4j.Slf4j; + +import java.util.function.Function; + +/** + * KjbProperty 싱글톤 홀더. + * + *

모든 곳에서 {@code KjbPropertyHolder.get()}으로 현재 KjbProperty에 접근합니다. + * eapim-admin에서 초기화 시 {@code initialize()}를 호출하고, + * MonitoringContext.refresh() 시 {@code reload()}를 호출하여 값을 갱신합니다.

+ * + *

사용 예시:

+ *
+ * // 값 접근
+ * String url = KjbPropertyHolder.get().getUmsHostUrl();
+ *
+ * // 초기화 (eapim-admin에서)
+ * KjbPropertyInjector injector = new KjbPropertyInjector(service, "Monitoring");
+ * KjbPropertyHolder.initialize(injector::inject);
+ *
+ * // reload (MonitoringContext.refresh() 시)
+ * KjbPropertyHolder.reload();
+ *
+ * // 테스트용
+ * KjbPropertyHolder.setForTest(mockProperty);
+ * 
+ */ +@Slf4j +public class KjbPropertyHolder { + + private static volatile KjbProperty instance = new KjbProperty(); + private static volatile Function injector; + + private KjbPropertyHolder() { + // 유틸리티 클래스 + } + + /** + * 현재 KjbProperty 인스턴스를 반환합니다. + */ + public static KjbProperty get() { + return instance; + } + + /** + * 초기화 함수를 등록하고 최초 로딩을 수행합니다. + * eapim-admin 부팅 시 MonitoringContextImpl.init()에서 호출됩니다. + * + * @param injectorFn KjbProperty를 DB에서 로딩하는 함수 (KjbPropertyInjector::inject) + */ + public static void initialize(Function injectorFn) { + injector = injectorFn; + reload(); + log.info("KjbPropertyHolder 초기화 완료"); + } + + /** + * DB에서 프로퍼티를 다시 로딩합니다. + * MonitoringContext.refresh() 호출 시 함께 호출됩니다. + */ + public static void reload() { + if (injector != null) { + try { + instance = injector.apply(new KjbProperty()); + log.info("KjbProperty reload 완료"); + } catch (Exception e) { + log.error("KjbProperty reload 실패: {}", e.getMessage(), e); + } + } else { + log.debug("KjbPropertyHolder: injector가 설정되지 않음 (테스트 환경일 수 있음)"); + } + } + + /** + * 테스트용 - 직접 인스턴스를 설정합니다. + */ + public static void setForTest(KjbProperty testProperty) { + instance = testProperty; + log.debug("KjbProperty 테스트 인스턴스 설정"); + } + + /** + * 테스트용 - 기본값으로 초기화합니다. + */ + public static void resetForTest() { + instance = new KjbProperty(); + injector = null; + log.debug("KjbPropertyHolder 테스트 초기화"); + } +} diff --git a/src/main/java/com/eactive/ext/kjb/obp/KjbObpModule.java b/src/main/java/com/eactive/ext/kjb/obp/KjbObpModule.java index 3dd8789..21e5aff 100644 --- a/src/main/java/com/eactive/ext/kjb/obp/KjbObpModule.java +++ b/src/main/java/com/eactive/ext/kjb/obp/KjbObpModule.java @@ -2,7 +2,7 @@ package com.eactive.ext.kjb.obp; import com.eactive.ext.kjb.common.KjbObpException; import com.eactive.ext.kjb.common.KjbProperty; -import lombok.Getter; +import com.eactive.ext.kjb.common.KjbPropertyHolder; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -10,30 +10,29 @@ import org.apache.commons.lang3.StringUtils; public class KjbObpModule { private static final String FAKE_PARTNER_CODE = "999999-99"; - private static KjbObpModule _instance; + private static volatile KjbObpModule instance; - @Getter - private final KjbProperty property; - private final ObpClient client; - - public static synchronized KjbObpModule getInstance(KjbProperty kjbProperty) { - if (_instance == null) { - _instance = new KjbObpModule(kjbProperty); - } else { - if (kjbProperty.equals(_instance.getProperty())) { - log.debug("KjbProperty 파라미터가 변경되어 KjbObpModule 인스턴스 재 생성"); - _instance = new KjbObpModule(kjbProperty); - } - } - return _instance; + private KjbObpModule() { + // 싱글톤 } - private KjbObpModule(KjbProperty kjbProperty) { - if (kjbProperty == null) { - throw new IllegalArgumentException("KjbProperty cannot be null"); + public static KjbObpModule getInstance() { + if (instance == null) { + synchronized (KjbObpModule.class) { + if (instance == null) { + instance = new KjbObpModule(); + } + } } - this.property = kjbProperty; - this.client = ObpClient.getInstance(kjbProperty); + return instance; + } + + private static KjbProperty getProperty() { + return KjbPropertyHolder.get(); + } + + private ObpClient getClient() { + return ObpClient.getInstance(); } /** @@ -53,13 +52,15 @@ public class KjbObpModule { throw new IllegalArgumentException("BizNo must be 10 digits. (input: " + bizNo + ")"); } + ObpClient client = getClient(); + // 가상모드: URL 미설정 시 가상 파트너코드 반환 if (!client.isRealMode()) { log.info("[OBP] 가상모드 - 가상 partnerCode 반환: {}", FAKE_PARTNER_CODE); return FAKE_PARTNER_CODE; } - String path = String.format(property.getObpUrlOrganizationFmt(), bizNo); + String path = String.format(getProperty().getObpUrlOrganizationFmt(), bizNo); log.debug("[OBP] queryPartnerCode - bizNo: {}, path: {}", bizNo, path); ObpResponse response = client.get(path); @@ -81,11 +82,4 @@ public class KjbObpModule { return org.getPartnerCode(); } - - /** - * ObpClient 반환 (직접 API 호출용) - */ - public ObpClient getClient() { - return client; - } } diff --git a/src/main/java/com/eactive/ext/kjb/obp/ObpClient.java b/src/main/java/com/eactive/ext/kjb/obp/ObpClient.java index 26684fb..bb6745a 100644 --- a/src/main/java/com/eactive/ext/kjb/obp/ObpClient.java +++ b/src/main/java/com/eactive/ext/kjb/obp/ObpClient.java @@ -1,7 +1,7 @@ package com.eactive.ext.kjb.obp; import com.eactive.ext.kjb.common.KjbProperty; -import lombok.Getter; +import com.eactive.ext.kjb.common.KjbPropertyHolder; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.hc.client5.http.classic.methods.HttpGet; @@ -22,46 +22,40 @@ import java.util.concurrent.*; @Slf4j public class ObpClient { - private static ObpClient _instance; + private static volatile ObpClient instance; - @Getter - private final KjbProperty property; - private final CloseableHttpClient httpClient; - private final RequestConfig requestConfig; - private final boolean isRealMode; - - public synchronized static ObpClient getInstance(KjbProperty kjbProperty) { - if (_instance == null) { - _instance = new ObpClient(kjbProperty); - } else { - if (kjbProperty.equals(_instance.getProperty())) { - log.debug("KjbProperty 파라미터가 변경되어 ObpClient 인스턴스 재 생성"); - _instance = new ObpClient(kjbProperty); - } - } - - return _instance; + private ObpClient() { + // 싱글톤 } - private ObpClient(KjbProperty kjbProperty) { - if (kjbProperty == null) { - throw new IllegalArgumentException("KjbProperty cannot be null"); + public static ObpClient getInstance() { + if (instance == null) { + synchronized (ObpClient.class) { + if (instance == null) { + instance = new ObpClient(); + } + } } + return instance; + } - this.property = kjbProperty; - this.isRealMode = StringUtils.isNotEmpty(kjbProperty.getObpUrl()); + private static KjbProperty getProperty() { + return KjbPropertyHolder.get(); + } - this.requestConfig = RequestConfig.custom() - .setConnectTimeout(Timeout.ofSeconds(kjbProperty.getObpConnectionTimeout())) - .setResponseTimeout(Timeout.ofSeconds(kjbProperty.getObpResponseTimeout())) + /** + * 실제 모드 여부 (URL이 설정되어 있는지 확인) + */ + public boolean isRealMode() { + return StringUtils.isNotEmpty(getProperty().getObpUrl()); + } + + private RequestConfig createRequestConfig() { + KjbProperty prop = getProperty(); + return RequestConfig.custom() + .setConnectTimeout(Timeout.ofSeconds(prop.getObpConnectionTimeout())) + .setResponseTimeout(Timeout.ofSeconds(prop.getObpResponseTimeout())) .build(); - - if (isRealMode) { - this.httpClient = HttpClients.createDefault(); - } else { - this.httpClient = null; - log.warn("[OBP] URL이 설정되지 않음. 실제 OBP 연동 없이 동작함"); - } } /** @@ -80,11 +74,11 @@ public class ObpClient { * @return ObpResponse */ public ObpResponse get(String path, Map additionalHeaders) { - String url = property.getObpUrl() + path; + String url = getProperty().getObpUrl() + path; HttpGet httpGet = new HttpGet(url); applyDefaultHeaders(httpGet); applyAdditionalHeaders(httpGet, additionalHeaders); - httpGet.setConfig(requestConfig); + httpGet.setConfig(createRequestConfig()); return execute(httpGet); } @@ -107,11 +101,11 @@ public class ObpClient { * @return ObpResponse */ public ObpResponse post(String path, String jsonBody, Map additionalHeaders) { - String url = property.getObpUrl() + path; + String url = getProperty().getObpUrl() + path; HttpPost httpPost = new HttpPost(url); applyDefaultHeaders(httpPost); applyAdditionalHeaders(httpPost, additionalHeaders); - httpPost.setConfig(requestConfig); + httpPost.setConfig(createRequestConfig()); if (StringUtils.isNotEmpty(jsonBody)) { httpPost.setEntity(EntityBuilder.create() @@ -124,9 +118,10 @@ public class ObpClient { } private void applyDefaultHeaders(HttpUriRequestBase request) { + KjbProperty prop = getProperty(); request.setHeader("Content-Type", "application/json; charset=utf-8"); - request.setHeader(property.getObpTrustSystemKey(), property.getObpTrustSystemValue()); - request.setHeader(property.getObpPartnerCodeKey(), property.getObpPartnerCodeValue()); + request.setHeader(prop.getObpTrustSystemKey(), prop.getObpTrustSystemValue()); + request.setHeader(prop.getObpPartnerCodeKey(), prop.getObpPartnerCodeValue()); } private void applyAdditionalHeaders(HttpUriRequestBase request, Map additionalHeaders) { @@ -136,7 +131,7 @@ public class ObpClient { } private ObpResponse execute(HttpUriRequestBase request) { - if (!isRealMode) { + if (!isRealMode()) { log.warn("[OBP] URL 미설정으로 실제 호출하지 않음. 요청: {} {}", request.getMethod(), request.getRequestUri()); ObpResponse mockResponse = new ObpResponse(); mockResponse.setStatus(200); @@ -146,7 +141,7 @@ public class ObpClient { ExecutorService executor = Executors.newSingleThreadExecutor(); - try { + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { log.debug("[OBP] 요청: {} {}", request.getMethod(), request.getRequestUri()); Future future = executor.submit(() -> @@ -162,7 +157,7 @@ public class ObpClient { }) ); - ObpResponse response = future.get(property.getObpTimeout(), TimeUnit.SECONDS); + ObpResponse response = future.get(getProperty().getObpTimeout(), TimeUnit.SECONDS); if (log.isDebugEnabled()) { log.debug("[OBP] 응답: status={}, body={}", response.getStatus(), response.getBody()); @@ -170,7 +165,7 @@ public class ObpClient { return response; - } catch (InterruptedException | ExecutionException | TimeoutException e) { + } catch (InterruptedException | ExecutionException | TimeoutException | java.io.IOException e) { log.error("[OBP] 호출 실패: {} {}", request.getMethod(), request.getRequestUri(), e); ObpResponse errorResponse = new ObpResponse(); errorResponse.setStatus(-1); @@ -180,11 +175,4 @@ public class ObpClient { executor.shutdown(); } } - - /** - * 실제 모드 여부 - */ - public boolean isRealMode() { - return isRealMode; - } } diff --git a/src/main/java/com/eactive/ext/kjb/sso/KjbSsoModule.java b/src/main/java/com/eactive/ext/kjb/sso/KjbSsoModule.java index 5e4ebb5..687c45e 100644 --- a/src/main/java/com/eactive/ext/kjb/sso/KjbSsoModule.java +++ b/src/main/java/com/eactive/ext/kjb/sso/KjbSsoModule.java @@ -1,6 +1,7 @@ package com.eactive.ext.kjb.sso; import com.eactive.ext.kjb.common.KjbProperty; +import com.eactive.ext.kjb.common.KjbPropertyHolder; import com.initech.eam.api.*; import com.initech.eam.base.APIException; import com.initech.eam.base.EmptyResultException; @@ -21,76 +22,75 @@ import java.util.Vector; @Slf4j public class KjbSsoModule { - private static KjbSsoModule instance; + private static volatile KjbSsoModule instance; - private KjbProperty prop; - private final NXContext context; - @Getter - private final Vector providerList; - - - /***[SERVICE CONFIGURATION]***********************************************************************/ - private final String SERVICE_NAME; - @Getter - private final String ascpUrl; - - /***[SSO CONFIGURATION]**]***********************************************************************/ - private final String NLS_URL; - private final String NLS_PORT; - private final String NLS_LOGIN_URL; - private final String NLS_LOGOUT_URL; - private final String NLS_ERROR_URL; - - /***[SSO ND LIST 운영]**]***********************************************************************/ - private final String ND_URL1; private final Vector PROVIDER_LIST = new Vector(); private final int COOKIE_SESSTION_TIME_OUT = 3000000; // 인증 타입 (ID/PW 방식 : 1, 인증서 : 3) private final String TOA = "1"; - private final String PROVIDER_DOMAIN; private final String SSO_DOMAIN = ".kjbank.com"; private final String COOKIE_PADDING = "_V42"; private static final int timeout = 15000; + private KjbSsoModule() { + CookieManager.setEncStatus(true); + SECode.setCookiePadding(COOKIE_PADDING); + } - public synchronized static KjbSsoModule getInstance(KjbProperty kjbProperty) { + public static KjbSsoModule getInstance() { if (instance == null) { - instance = new KjbSsoModule(kjbProperty); - } else { - if (!instance.prop.equals(kjbProperty)) { - instance.prop = kjbProperty; + synchronized (KjbSsoModule.class) { + if (instance == null) { + instance = new KjbSsoModule(); + } } } return instance; } - private KjbSsoModule(KjbProperty kjbProperty) { - this.prop = kjbProperty; + private static KjbProperty getProperty() { + return KjbPropertyHolder.get(); + } - ascpUrl = prop.getUrl() + prop.getSsoAscpUri(); + private String getServiceName() { + return getProperty().getSsoServiceName(); + } - SERVICE_NAME = prop.getSsoServiceName(); - NLS_URL = "http://" + prop.getSsoDomain(); - NLS_PORT = String.valueOf(prop.getSsoNlsPort()); - NLS_LOGIN_URL = NLS_URL + ":" + NLS_PORT + "/nls3/clientLogin.jsp"; - NLS_LOGOUT_URL = NLS_URL + ":" + NLS_PORT + "/nls3/NCLogout.jsp"; - NLS_ERROR_URL = NLS_URL + ":" + NLS_PORT + "/nls3/error.jsp"; - - ND_URL1 = "http://" + prop.getSsoDomain() + ":5480"; - - PROVIDER_DOMAIN = prop.getSsoDomain(); + public String getAscpUrl() { + KjbProperty prop = getProperty(); + return prop.getUrl() + prop.getSsoAscpUri(); + } - this.providerList = new Vector<>(); - PROVIDER_LIST.add(prop.getSsoDomain()); + private String getNlsUrl() { + return "http://" + getProperty().getSsoDomain(); + } - context = new NXContext(Collections.singletonList(ND_URL1), timeout); - CookieManager.setEncStatus(true); - SECode.setCookiePadding(COOKIE_PADDING); - - - log.debug("KjbProperty : {}", prop.toString()); + private String getNlsPort() { + return String.valueOf(getProperty().getSsoNlsPort()); + } + + private String getNlsLoginUrl() { + return getNlsUrl() + ":" + getNlsPort() + "/nls3/clientLogin.jsp"; + } + + private String getNlsLogoutUrl() { + return getNlsUrl() + ":" + getNlsPort() + "/nls3/NCLogout.jsp"; + } + + private String getNlsErrorUrl() { + return getNlsUrl() + ":" + getNlsPort() + "/nls3/error.jsp"; + } + + private String getNdUrl1() { + return "http://" + getProperty().getSsoDomain() + ":5480"; + } + + public Vector getProviderList() { + Vector list = new Vector<>(); + list.add(getProperty().getSsoDomain()); + return list; } @@ -99,18 +99,15 @@ public class KjbSsoModule { NXContext context = null; try { List serverurlList = new ArrayList<>(); - serverurlList.add(ND_URL1); + serverurlList.add(getNdUrl1()); context = new NXContext(serverurlList); CookieManager.setEncStatus(true); - - PROVIDER_LIST.add(prop.getSsoDomain()); - //NLS3 web.xml의 CookiePadding 값과 같아야 한다. 안그럼 검증 페일남 - SECode.setCookiePadding("_V42"); + SECode.setCookiePadding(COOKIE_PADDING); } catch (Exception e) { log.warn("getContext", e); - } + } return context; } @@ -134,11 +131,12 @@ public class KjbSsoModule { try { context = getContext(); userAPI = new NXUserAPI(context); + String serviceName = getServiceName(); log.info("##############################################"); log.info("sso_id 2: "+sso_id); - log.info("SERVICE_NAME : "+ SERVICE_NAME); + log.info("SERVICE_NAME : "+ serviceName); log.info("##############################################"); - NXAccount account = userAPI.getUserAccount(sso_id, SERVICE_NAME); + NXAccount account = userAPI.getUserAccount(sso_id, serviceName); log.info(account.toString()); retValue = account.getAccountName(); log.info("retValue = " + retValue); @@ -156,9 +154,9 @@ public class KjbSsoModule { */ public void goLoginPage(HttpServletResponse response, String uurl) throws Exception { - CookieManager.addCookie(SECode.USER_URL, uurl, ".kjbank.com", response); - CookieManager.addCookie(SECode.R_TOA, TOA, ".kjbank.com", response); - response.sendRedirect(NLS_LOGIN_URL + "?UURL=" + uurl); + CookieManager.addCookie(SECode.USER_URL, uurl, SSO_DOMAIN, response); + CookieManager.addCookie(SECode.R_TOA, TOA, SSO_DOMAIN, response); + response.sendRedirect(getNlsLoginUrl() + "?UURL=" + uurl); } /** @@ -167,9 +165,9 @@ public class KjbSsoModule { * @throws Exception */ public void goLoginPage(HttpServletResponse response) throws Exception { - CookieManager.addCookie(SECode.USER_URL, ascpUrl, SSO_DOMAIN, response); + CookieManager.addCookie(SECode.USER_URL, getAscpUrl(), SSO_DOMAIN, response); CookieManager.addCookie(SECode.R_TOA, TOA, SSO_DOMAIN, response); - response.sendRedirect(NLS_LOGIN_URL); + response.sendRedirect(getNlsLoginUrl()); } /** @@ -178,13 +176,12 @@ public class KjbSsoModule { * @param response * @return */ - public String getEamSessionCheck(HttpServletRequest request,HttpServletResponse response){ + public String getEamSessionCheck(HttpServletRequest request, HttpServletResponse response) { String retCode = ""; try { - retCode = CookieManager.verifyNexessCookie(request, response, 10, COOKIE_SESSTION_TIME_OUT,PROVIDER_LIST); + retCode = CookieManager.verifyNexessCookie(request, response, 10, COOKIE_SESSTION_TIME_OUT, getProviderList()); } catch(Exception npe) { log.warn("getEamSessionCheck", npe); -// npe.printStackTrace(); } return retCode; } @@ -195,11 +192,11 @@ public class KjbSsoModule { * @param response * @return */ - public String getEamSessionCheck2(HttpServletRequest request,HttpServletResponse response) - { + public String getEamSessionCheck2(HttpServletRequest request, HttpServletResponse response) { String retCode = ""; try { - NXNLSAPI nxNLSAPI = new NXNLSAPI(context); + NXContext ctx = getContext(); + NXNLSAPI nxNLSAPI = new NXNLSAPI(ctx); retCode = nxNLSAPI.readNexessCookie(request, response, 0, 0); } catch(Exception npe) { log.error("KjbSsoModule-getEamSessionCheck2 Exception", npe); @@ -213,10 +210,10 @@ public class KjbSsoModule { * @param error_code * @throws Exception */ - public void goErrorPage(HttpServletResponse response, int error_code)throws Exception { + public void goErrorPage(HttpServletResponse response, int error_code) throws Exception { CookieManager.removeNexessCookie(SSO_DOMAIN, response); - CookieManager.addCookie(SECode.USER_URL, ascpUrl, SSO_DOMAIN, response); - response.sendRedirect(NLS_ERROR_URL + "?errorCode=" + error_code); + CookieManager.addCookie(SECode.USER_URL, getAscpUrl(), SSO_DOMAIN, response); + response.sendRedirect(getNlsErrorUrl() + "?errorCode=" + error_code); } /** diff --git a/src/main/java/com/eactive/ext/kjb/ums/KjbEmailSendModule.java b/src/main/java/com/eactive/ext/kjb/ums/KjbEmailSendModule.java index 99cd61b..ce83a77 100644 --- a/src/main/java/com/eactive/ext/kjb/ums/KjbEmailSendModule.java +++ b/src/main/java/com/eactive/ext/kjb/ums/KjbEmailSendModule.java @@ -5,6 +5,7 @@ import com.eactive.apim.portal.template.entity.MessageRequest; import com.eactive.apim.portal.template.repository.MessageRequestRepository; import com.eactive.ext.kjb.common.KjbEaiBatchException; import com.eactive.ext.kjb.common.KjbProperty; +import com.eactive.ext.kjb.common.KjbPropertyHolder; import com.eactive.ext.kjb.utils.ValidationUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -18,24 +19,35 @@ import java.util.function.BiConsumer; public class KjbEmailSendModule { public final static int[] ALLOW_CHANNELS = { MessageCode.Channels.EMAIL.getValue() }; - private static KjbEmailSendModule instance = null; - private static KjbProperty prop; + private static volatile KjbEmailSendModule instance; + private MessageRequestRepository repo; - private final MessageRequestRepository repo; - - - public static synchronized KjbEmailSendModule getInstance(KjbProperty property, - MessageRequestRepository messageRequestRepository) { - - ValidationUtil.validateOrThrow(property); + private KjbEmailSendModule() { + // 싱글톤 + } + public static KjbEmailSendModule getInstance() { if (instance == null) { - instance = new KjbEmailSendModule(property, messageRequestRepository); + synchronized (KjbEmailSendModule.class) { + if (instance == null) { + instance = new KjbEmailSendModule(); + } + } } - return instance; } + /** + * MessageRequestRepository 설정 (eapim-admin 초기화 시 호출) + */ + public void setRepository(MessageRequestRepository repository) { + this.repo = repository; + } + + private static KjbProperty getProperty() { + return KjbPropertyHolder.get(); + } + public static boolean isAllowChannel(MessageRequest message) { for (int channel : ALLOW_CHANNELS) { if ((message.getMessageCode().getChannels() & channel) == channel) { @@ -47,6 +59,8 @@ public class KjbEmailSendModule { public static void environmentCheck() { + KjbProperty prop = getProperty(); + if (StringUtils.isEmpty(prop.getEaiBatchUrl())) { log.warn("EAI_BATCH_URL 가 설정되지 않음. 실제 EAI 배치 연동 없이 동작함"); } @@ -101,19 +115,6 @@ public class KjbEmailSendModule { log.info("KjbEmailSendModule - Environment check passed."); } - - - private KjbEmailSendModule(KjbProperty property, - MessageRequestRepository repo) { - this.repo = repo; - - if (property != null && prop == null) { - prop = property; - } - - environmentCheck(); - } - public void sendEmail(MessageRequest messageRequest) throws KjbEaiBatchException { String serviceId = "UNKNOWN"; @@ -135,7 +136,7 @@ public class KjbEmailSendModule { repo.save(messageRequest); } - EmailJob job = EmailJob.create(prop, messageRequest, repo); + EmailJob job = EmailJob.create(getProperty(), messageRequest, repo); job.sendEmail(); log.debug("JSON : {}", job.generateJSON(true)); diff --git a/src/main/java/com/eactive/ext/kjb/ums/KjbUmsService.java b/src/main/java/com/eactive/ext/kjb/ums/KjbUmsService.java index 7d1a546..281fee7 100644 --- a/src/main/java/com/eactive/ext/kjb/ums/KjbUmsService.java +++ b/src/main/java/com/eactive/ext/kjb/ums/KjbUmsService.java @@ -3,6 +3,7 @@ package com.eactive.ext.kjb.ums; import com.eactive.apim.portal.template.entity.MessageCode; import com.eactive.apim.portal.template.entity.MessageRequest; import com.eactive.ext.kjb.common.KjbProperty; +import com.eactive.ext.kjb.common.KjbPropertyHolder; import com.eactive.ext.kjb.common.KjbUmsException; import com.eactive.ext.kjb.ums.gson.IUmsGsonObject; import com.eactive.ext.kjb.ums.gson.UmsRequestPayload; @@ -39,39 +40,42 @@ public class KjbUmsService { private final static String CONTENT_TYPE = "application/json; charset=utf-8"; private final static String AUTHORIZATION_FMT = "Bearer %s"; - private final KjbProperty property; - private final boolean isRealMode; - private final CloseableHttpClient httpClient; - private final RequestConfig requestConfig; + private static volatile KjbUmsService instance; + private KjbUmsService() { + // 싱글톤 + } - public KjbUmsService(KjbProperty property) { - if (property == null) { - log.error("[KJB-UMS] 파라미터 설정 되지 않음"); - throw new IllegalArgumentException("property is null"); - } - - isRealMode = property.getUmsHostUrl() != null && StringUtils.isNotEmpty(property.getUmsHostUrl().trim()); - - if (isRealMode) { - try { - ValidationUtil.validateOrThrow(property); - } catch (Exception e) { - log.error("[KJB-UMS] 파라미터 설정 오류", e); - throw e; + public static KjbUmsService getInstance() { + if (instance == null) { + synchronized (KjbUmsService.class) { + if (instance == null) { + instance = new KjbUmsService(); + } } - - httpClient = HttpClients.createDefault(); - requestConfig = RequestConfig.custom() - .setConnectTimeout(Timeout.ofSeconds(property.getEaiBatchConnectionTimeout())) - .setResponseTimeout(Timeout.ofSeconds(property.getEaiBatchResponseTimeout())) - .build(); - } else { - httpClient = HttpClients.createDefault(); - requestConfig = null; } + return instance; + } - this.property = property; + private KjbProperty getProperty() { + return KjbPropertyHolder.get(); + } + + private boolean isRealMode() { + String url = getProperty().getUmsHostUrl(); + return url != null && StringUtils.isNotEmpty(url.trim()); + } + + private CloseableHttpClient createHttpClient() { + return HttpClients.createDefault(); + } + + private RequestConfig createRequestConfig() { + KjbProperty prop = getProperty(); + return RequestConfig.custom() + .setConnectTimeout(Timeout.ofSeconds(prop.getUmsConnectionTimeout())) + .setResponseTimeout(Timeout.ofSeconds(prop.getUmsResponseTimeout())) + .build(); } @@ -142,13 +146,14 @@ public class KjbUmsService { } private UmsCallResult call(String url, UmsRequestPayload requestPayload) throws KjbUmsException { + KjbProperty prop = getProperty(); ExecutorService executor = Executors.newSingleThreadExecutor(); Gson gson = new Gson(); String json = gson.toJson(requestPayload); - HttpPost httpPost = new HttpPost(property.getUmsHostUrl() + url); + HttpPost httpPost = new HttpPost(prop.getUmsHostUrl() + url); httpPost.setHeader("Content-Type", CONTENT_TYPE); - httpPost.setHeader("Authorization", String.format(AUTHORIZATION_FMT, property.getUmsApiKey())); + httpPost.setHeader("Authorization", String.format(AUTHORIZATION_FMT, prop.getUmsApiKey())); httpPost.setEntity(EntityBuilder.create().setText(json).setContentType(ContentType.APPLICATION_JSON).build()); if (log.isDebugEnabled()) { @@ -161,52 +166,54 @@ public class KjbUmsService { } } - httpPost.setConfig(requestConfig); + httpPost.setConfig(createRequestConfig()); - if (isRealMode) { - Future future = executor.submit(() -> { - return httpClient.execute(httpPost, res -> { - try { - UmsCallResult result; - String body = EntityUtils.toString(res.getEntity()); - if (log.isDebugEnabled()) { - log.debug("Response - {}", body); - } - result = gson.fromJson(body, UmsCallResult.class); - result.setUmsMessageId(requestPayload.getMessageIdentityNo()); - result.setSuccess(true); - return result; - } catch (JsonSyntaxException e) { - log.error("UMS Call error(JSON Syntax)", e); - return UmsCallResult.builder() - .umsMessageId(requestPayload.getMessageIdentityNo()) - .isSuccess(false) - .throwable(e) - .build(); - } catch (Exception e) { - log.error("UMS Call error", e); - return UmsCallResult.builder() - .umsMessageId(requestPayload.getMessageIdentityNo()) - .isSuccess(false) - .throwable(e) - .build(); - } finally { - log.debug("Response status - {}", res.getCode()); + if (isRealMode()) { + try (CloseableHttpClient httpClient = createHttpClient()) { + Future future = executor.submit(() -> { + return httpClient.execute(httpPost, res -> { + try { + UmsCallResult result; + String body = EntityUtils.toString(res.getEntity()); + if (log.isDebugEnabled()) { + log.debug("Response - {}", body); + } + result = gson.fromJson(body, UmsCallResult.class); + result.setUmsMessageId(requestPayload.getMessageIdentityNo()); + result.setSuccess(true); + return result; + } catch (JsonSyntaxException e) { + log.error("UMS Call error(JSON Syntax)", e); + return UmsCallResult.builder() + .umsMessageId(requestPayload.getMessageIdentityNo()) + .isSuccess(false) + .throwable(e) + .build(); + } catch (Exception e) { + log.error("UMS Call error", e); + return UmsCallResult.builder() + .umsMessageId(requestPayload.getMessageIdentityNo()) + .isSuccess(false) + .throwable(e) + .build(); + } finally { + log.debug("Response status - {}", res.getCode()); - if (res.getCode() != 200) { - Arrays.asList(res.getHeaders()).forEach(o -> { - log.warn("[Header] {}: {}", o.getName(), o.getValue()); - }); + if (res.getCode() != 200) { + Arrays.asList(res.getHeaders()).forEach(o -> { + log.warn("[Header] {}: {}", o.getName(), o.getValue()); + }); + } } - } + }); }); - }); - try { - return future.get(property.getUmsTimeout(), TimeUnit.SECONDS); - } catch (InterruptedException | ExecutionException | TimeoutException e) { - log.error("EAI Batch call exception", e); - throw new KjbUmsException("EAI Ums call failed", e); + return future.get(prop.getUmsTimeout(), TimeUnit.SECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException | IOException e) { + log.error("UMS call exception", e); + throw new KjbUmsException("UMS call failed", e); + } finally { + executor.shutdown(); } } else { log.warn("UMS URL 미지정으로 실제 호출을 진행하지 않음.");