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 미지정으로 실제 호출을 진행하지 않음.");