diff --git a/build.gradle b/build.gradle
index 7f90ea0..de5348c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,9 +1,10 @@
plugins {
- id 'java-library'
+ id 'java-library'
id 'eclipse'
- id 'eclipse-wtp'
+ id 'eclipse-wtp'
id 'idea'
id 'war'
+ id 'com.diffplug.eclipse.apt' version '3.41.1'
}
group 'com.eactive'
@@ -31,11 +32,11 @@ allprojects {
project.webAppDirName = 'WebContent'
java {
- toolchain {
- languageVersion = JavaLanguageVersion.of(8)
- }
+ toolchain {
+ languageVersion = JavaLanguageVersion.of(8)
+ }
}
-
+
sourceSets {
main {
java {
@@ -45,56 +46,56 @@ sourceSets {
}
compileJava {
- options.encoding = 'UTF-8'
- options.compilerArgs = ['-parameters']
- options.generatedSourceOutputDirectory = project.file(generatedJavaDir)
+ options.encoding = 'UTF-8'
+ options.compilerArgs = ['-parameters']
+ options.generatedSourceOutputDirectory = project.file(generatedJavaDir)
+
+ aptOptions {
+ processorArgs = [ 'querydsl.generatedAnnotationClass' : 'com.querydsl.core.annotations.Generated' ]
+ }
}
war {
- def profile = project.findProperty("profile") ?: "tomcat"
-
- if (profile == "weblogic") {
- webXml = file("WebContent/WEB-INF/weblogic-web.xml")ㅇ
- exclude 'WEB-INF/web.xml'
- }
-
-
- // rootSpec.exclude '**/persistence.xml'
- exclude '**/context.xml'
- exclude '**/context-*.xml'
- archiveFileName = "eapim-admin.war"
- duplicatesStrategy = DuplicatesStrategy.WARN
+ def profile = project.findProperty("profile") ?: "tomcat"
+
+ if (profile == "weblogic") {
+ webXml = file("WebContent/WEB-INF/weblogic-web.xml")
+ exclude 'WEB-INF/web.xml'
+ }
+
+
+ // rootSpec.exclude '**/persistence.xml'
+ exclude '**/context.xml'
+ exclude '**/context-*.xml'
+ archiveFileName = "eapim-admin.war"
+ duplicatesStrategy = DuplicatesStrategy.WARN
}
tasks.withType(JavaCompile) {
- options.encoding = 'UTF-8'
- options.compilerArgs += ['-parameters', "-Xlint:unchecked", "-Xlint:deprecation"]
+ options.encoding = 'UTF-8'
+ options.compilerArgs += ['-parameters', "-Xlint:unchecked", "-Xlint:deprecation"]
}
dependencies {
-
- annotationProcessor "org.projectlombok:lombok:1.18.28",
- "org.projectlombok:lombok-mapstruct-binding:0.2.0",
- "org.mapstruct:mapstruct-processor:1.5.5.Final"
- annotationProcessor "com.querydsl:querydsl-apt:${queryDslVersion}:jpa",
- "jakarta.persistence:jakarta.persistence-api:2.2.3",
- "jakarta.annotation:jakarta.annotation-api:1.3.5"
-
+
+ annotationProcessor "org.projectlombok:lombok:1.18.28", "org.projectlombok:lombok-mapstruct-binding:0.2.0", "org.mapstruct:mapstruct-processor:1.5.5.Final"
+ annotationProcessor "com.querydsl:querydsl-apt:${queryDslVersion}:jpa", "jakarta.persistence:jakarta.persistence-api:2.2.3", "jakarta.annotation:jakarta.annotation-api:1.3.5"
+
implementation project(':elink-online-core')
implementation project(':elink-online-transformer')
implementation project(':elink-online-common')
- implementation project(':elink-online-emsclient')
- implementation project(':elink-portal-common')
- //implementation project(':kjb-safedb')
- implementation project(":eapim-admin-djb")
+ implementation project(':elink-online-emsclient')
+ implementation project(':elink-portal-common')
+ //implementation project(':kjb-safedb')
+ //implementation project(":eapim-admin-djb")
/* Custom Libs (damo-manager.jar 는 Tomcat lib 가 런타임 제공 → compileOnly, WAR 미포함) */
implementation fileTree(dir: 'libs', include: ['*.jar'], exclude: ['damo-manager.jar'])
compileOnly files('libs/damo-manager.jar')
- //implementation "org.dom4j:dom4j:2.1.3"
+ //implementation "org.dom4j:dom4j:2.1.3"
//implementation "com.rabbitmq:amqp-client:3.6.6"
implementation "commons-primitives:commons-primitives:1.0"
@@ -116,10 +117,10 @@ dependencies {
// https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api
compileOnly group: 'javax.servlet', name: 'javax.servlet-api', version: '4.0.1'
-
+
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.13.1'
//implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-xml', version: '2.13.1'
- implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.1'
+ implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.1'
implementation "javax.jms:javax.jms-api:2.0"
implementation "org.snmp4j:snmp4j:1.10.1"
@@ -186,32 +187,32 @@ dependencies {
implementation 'ch.qos.logback:logback-classic:1.2.10'
implementation 'ch.qos.logback:logback-access:1.2.10'
implementation 'ch.qos.logback:logback-core:1.2.10'
+
+ implementation files("libs/eai-bap-client.jar")
+
+ compileOnly 'javax.xml.bind:jaxb-api:2.3.1'
+
+ //implementation 'org.postgresql:postgresql:42.2.23'
+
+ implementation 'backport-util-concurrent:backport-util-concurrent:3.0'
+
+ implementation ('software.amazon.awssdk:s3:2.20.142') {
+ exclude group: 'org.slf4j', module: 'slf4j-api'
+ exclude group: 'org.slf4j', module: 'logback-classic'
+ }
+ implementation 'software.amazon.awssdk:sso:2.20.142'
+ implementation 'software.amazon.awssdk:sts:2.20.142'
- implementation files("libs/eai-bap-client.jar")
+ implementation group: 'commons-net', name: 'commons-net', version: '3.5'
- compileOnly 'javax.xml.bind:jaxb-api:2.3.1'
+ // JDK 8 의 rt.jar 에는 org.w3c.dom.ElementTraversal 이 없어 xercesImpl 가 NCDFE 를 일으킴.
+ // xml-apis 1.4.01 에 그 클래스가 포함됨. 직접 의존성으로 묶어 WAR 에 패키징되도록 함.
+ implementation 'xml-apis:xml-apis:1.4.01'
- //implementation 'org.postgresql:postgresql:42.2.23'
-
- implementation 'backport-util-concurrent:backport-util-concurrent:3.0'
-
- implementation ('software.amazon.awssdk:s3:2.20.142') {
- exclude group: 'org.slf4j', module: 'slf4j-api'
- exclude group: 'org.slf4j', module: 'logback-classic'
- }
- implementation 'software.amazon.awssdk:sso:2.20.142'
- implementation 'software.amazon.awssdk:sts:2.20.142'
-
- implementation group: 'commons-net', name: 'commons-net', version: '3.5'
-
- // JDK 8 의 rt.jar 에는 org.w3c.dom.ElementTraversal 이 없어 xercesImpl 가 NCDFE 를 일으킴.
- // xml-apis 1.4.01 에 그 클래스가 포함됨. 직접 의존성으로 묶어 WAR 에 패키징되도록 함.
- implementation 'xml-apis:xml-apis:1.4.01'
-
- testRuntimeOnly 'com.h2database:h2:2.1.214'
- testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
- testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
- testImplementation 'org.springframework.boot:spring-boot-starter-test:2.6.15'
+ testRuntimeOnly 'com.h2database:h2:2.1.214'
+ testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
+ testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
+ testImplementation 'org.springframework.boot:spring-boot-starter-test:2.6.15'
}
test {
@@ -219,9 +220,9 @@ test {
}
configurations.all {
- exclude group: 'log4j', module: 'log4j'
- exclude group: 'org.apache.activemq'
- exclude group: 'org.codehaus.jackson'
+ exclude group: 'log4j', module: 'log4j'
+ exclude group: 'org.apache.activemq'
+ exclude group: 'org.codehaus.jackson'
resolutionStrategy {
// 10 minute cache of dynamic version navigation
cacheDynamicVersionsFor 10, 'minutes'
@@ -245,25 +246,29 @@ task settingEclipseEncoding {
}
task initDirs() {
- file(generatedJavaDir).mkdirs()
+ file(generatedJavaDir).mkdirs()
}
eclipse {
- wtp {
- component {
- contextPath = 'monitoring'
- }
- }
- synchronizationTasks settingEclipseEncoding, initDirs
- jdt {
-
- }
- project {
- if (!natures.contains('org.eclipse.buildship.core.gradleprojectnature')) {
- natures.add('org.eclipse.buildship.core.gradleprojectnature')
- buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
- }
- }
+ wtp {
+ component {
+ contextPath = 'monitoring'
+ }
+ }
+ synchronizationTasks settingEclipseEncoding, initDirs
+ jdt {
+ apt {
+ // generated 된 패스 경로를 .setting/org.eclipse.jdt.apt.core.prefs 의 org.eclipse.jdt.apt.genSrcDir에 적용한다.
+ // project > properties > Java Compiler > Annoation Processing 화면에서 확인 가능하다.
+ genSrcDir = file(generatedJavaDir)
+ }
+ }
+ project {
+ if (!natures.contains('org.eclipse.buildship.core.gradleprojectnature')) {
+ natures.add('org.eclipse.buildship.core.gradleprojectnature')
+ buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
+ }
+ }
}
tasks.withType(JavaCompile) {
diff --git a/settings.gradle b/settings.gradle
index 3656dda..9753534 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -7,7 +7,7 @@ include 'elink-online-common'
include 'elink-online-emsclient'
include 'elink-portal-common'
//include 'kjb-safedb'
-include 'eapim-admin-djb'
+//include 'eapim-admin-djb'
project (':elink-online-core-jpa').projectDir = new File(settingsDir, "../eapim-online/elink-online-core-jpa")
project (':elink-online-core').projectDir = new File(settingsDir, "../eapim-online/elink-online-core")
@@ -16,4 +16,4 @@ project (':elink-online-common').projectDir = new File(settingsDir, "../eapim-on
project (':elink-online-emsclient').projectDir = new File(settingsDir, "../eapim-online/elink-online-emsclient")
project (':elink-portal-common').projectDir = new File(settingsDir, "../elink-portal-common")
//project (':kjb-safedb').projectDir = new File(settingsDir, "../kjb-safedb")
-project (':eapim-admin-djb').projectDir = new File(settingsDir, "../eapim-admin-djb")
\ No newline at end of file
+//project (':eapim-admin-djb').projectDir = new File(settingsDir, "../eapim-admin-djb")
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/rms/common/context/MonitoringContextImpl.java b/src/main/java/com/eactive/eai/rms/common/context/MonitoringContextImpl.java
index a4a6e68..cb67ded 100644
--- a/src/main/java/com/eactive/eai/rms/common/context/MonitoringContextImpl.java
+++ b/src/main/java/com/eactive/eai/rms/common/context/MonitoringContextImpl.java
@@ -21,8 +21,8 @@ import com.eactive.eai.rms.common.util.ContainerUtil;
import com.eactive.eai.rms.data.entity.man.monitoringProperty.MonitoringPropertyId;
import com.eactive.eai.rms.data.entity.man.monitoringProperty.service.MonitoringPropertyGroupService;
import com.eactive.eai.rms.data.entity.man.monitoringProperty.service.MonitoringPropertyService;
-import com.eactive.ext.kjb.common.KjbPropertyHolder;
-import com.eactive.ext.kjb.util.KjbPropertyInjector;
+import com.eactive.eai.rms.ext.djb.common.DjbPropertyHolder;
+import com.eactive.eai.rms.ext.djb.common.DjbPropertyInjector;
@Service("monitoringContext")
@Transactional(transactionManager = "transactionManagerForEMS")
@@ -45,7 +45,7 @@ class MonitoringContextImpl implements MonitoringContext {
public void refresh() {
init();
- KjbPropertyHolder.reload();
+ DjbPropertyHolder.reload();
}
public void refresh(String propName) {
@@ -85,9 +85,9 @@ class MonitoringContextImpl implements MonitoringContext {
setPortMapper(monitoringContextDAO.getPortMap());
- // KjbPropertyHolder 초기화
- KjbPropertyInjector injector = new KjbPropertyInjector(monitoringPropertyService, "Monitoring");
- KjbPropertyHolder.initialize(injector::inject);
+ // DjbPropertyHolder 초기화
+ DjbPropertyInjector injector = new DjbPropertyInjector(monitoringPropertyService, "Monitoring");
+ DjbPropertyHolder.initialize(injector::inject);
logger.info("SSO AgentId : " + System.getProperty(EAI_AGENTID));
diff --git a/src/main/java/com/eactive/eai/rms/common/login/MainController.java b/src/main/java/com/eactive/eai/rms/common/login/MainController.java
index 78f7a2d..e96c05a 100644
--- a/src/main/java/com/eactive/eai/rms/common/login/MainController.java
+++ b/src/main/java/com/eactive/eai/rms/common/login/MainController.java
@@ -32,7 +32,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.View;
import com.eactive.eai.common.seed.Seed;
-import com.eactive.eai.rms.ext.kjb.smsauth.SmsAuthService;
import com.eactive.ext.djb.DamoManager;
import com.eactive.eai.data.converter.LocalDateTimeFormatters;
import com.eactive.eai.rms.common.context.MonitoringContext;
@@ -51,6 +50,7 @@ import com.eactive.eai.rms.data.entity.man.user.UserLoginHistoryService;
import com.eactive.eai.rms.data.entity.man.user.UserRole;
import com.eactive.eai.rms.data.entity.man.user.UserRoleService;
import com.eactive.eai.rms.data.entity.man.user.UserServiceTypeService;
+import com.eactive.eai.rms.ext.djb.smsauth.SmsAuthService;
@Controller
public class MainController implements InterceptorSkipController {
diff --git a/src/main/java/com/eactive/eai/rms/ext/djb/common/DjbProperty.java b/src/main/java/com/eactive/eai/rms/ext/djb/common/DjbProperty.java
new file mode 100644
index 0000000..b6cbd00
--- /dev/null
+++ b/src/main/java/com/eactive/eai/rms/ext/djb/common/DjbProperty.java
@@ -0,0 +1,121 @@
+package com.eactive.eai.rms.ext.djb.common;
+
+import lombok.Data;
+import org.hibernate.validator.constraints.NotEmpty;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.Pattern;
+
+@Data
+public class DjbProperty {
+
+ // SMS 2차 인증
+
+ @DjbPropertyValue(
+ key = "djb.sms_auth.enabled",
+ defaultValue = "true",
+ description = "SMS 2차 인증 사용 여부. true 시 휴대폰번호 없는 사용자는 ID/PW 로그인 불가")
+ private boolean smsAuthEnabled = false;
+
+ @DjbPropertyValue(
+ key = "djb.sms_auth.mode",
+ defaultValue = "real",
+ description = "인증번호 생성 모드: real(랜덤), hhmm00(현재시각+00), fixed(고정값)")
+ @Pattern(regexp = "^(real|hhmm00|fixed)$", message = "djb.sms_auth.mode는 real, hhmm00, fixed 중 하나여야 합니다.")
+ private String smsAuthMode = "real";
+
+ @DjbPropertyValue(
+ key = "djb.sms_auth.fixed_value",
+ defaultValue = "654321",
+ description = "mode가 fixed일 때 사용할 고정 인증번호 (6자리 숫자)")
+ @Pattern(regexp = "^\\d{6}$", message = "djb.sms_auth.fixed_value는 6자리 숫자여야 합니다.")
+ private String smsAuthFixedValue = "654321";
+
+
+ @DjbPropertyValue(
+ key = "djb.api.allow_ip_list",
+ description = "API 접근 허용 IP 목록 (콤마(,)로 구분된 IP들, 예: 192.168.0.1, 192.168.1.*,127.*.*.*",
+ defaultValue = "10.15.106.*, 10.14.8.*, 10.15.8.*, 192.168.240.*, 127.0.0.1, 192.168.132.*, 192.168.131.*"
+ )
+ private String apiAllowIpList = "10.15.106.*, 10.14.8.*, 10.15.8.*, 192.168.240.*, 127.0.0.1, 192.168.132.*, 192.168.131.*";
+
+ @DjbPropertyValue(
+ key = "djb.api_gw_metric.page_size",
+ description = "API GW Metric 조회시 페이지 크기 설정 (Integer, 0 = 무한, 기본값 10000)",
+ defaultValue = "10000"
+ )
+ private Integer apiGwMetricPageSize = 10000;
+
+
+
+ public String toJsonString(boolean isPretty) {
+ return isPretty
+ ? new GsonBuilder().setPrettyPrinting().create().toJson(this)
+ : new Gson().toJson(this);
+ }
+
+
+ // 기본 프로퍼티 목록을 콘솔로 출력 (가이드용)
+ public static void main(String[] args) {
+ System.out.println("| Key | Default Value | Description |");
+ System.out.println("|-----|---------------|-------------|");
+
+ for (java.lang.reflect.Field field : DjbProperty.class.getDeclaredFields()) {
+ DjbPropertyValue annotation = field.getAnnotation(DjbPropertyValue.class);
+ if (annotation != null) {
+ String key = annotation.key();
+ String defaultValue = annotation.defaultValue();
+ String description = annotation.description();
+ System.out.printf("| %s | %s | %s |%n", key, defaultValue, description);
+ }
+ }
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/com/eactive/eai/rms/ext/djb/common/DjbPropertyHolder.java b/src/main/java/com/eactive/eai/rms/ext/djb/common/DjbPropertyHolder.java
new file mode 100644
index 0000000..d5f1ead
--- /dev/null
+++ b/src/main/java/com/eactive/eai/rms/ext/djb/common/DjbPropertyHolder.java
@@ -0,0 +1,92 @@
+package com.eactive.eai.rms.ext.djb.common;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.function.Function;
+
+/**
+ * DjbProperty 싱글톤 홀더.
+ *
+ *
모든 곳에서 {@code DjbPropertyHolder.get()}으로 현재 DjbProperty에 접근합니다.
+ * eapim-admin에서 초기화 시 {@code initialize()}를 호출하고,
+ * MonitoringContext.refresh() 시 {@code reload()}를 호출하여 값을 갱신합니다.
+ *
+ * 사용 예시:
+ *
+ * // 값 접근
+ * String url = DjbPropertyHolder.get().getUmsHostUrl();
+ *
+ * // 초기화 (eapim-admin에서)
+ * DjbPropertyInjector injector = new DjbPropertyInjector(service, "Monitoring");
+ * DjbPropertyHolder.initialize(injector::inject);
+ *
+ * // reload (MonitoringContext.refresh() 시)
+ * DjbPropertyHolder.reload();
+ *
+ * // 테스트용
+ * DjbPropertyHolder.setForTest(mockProperty);
+ *
+ */
+@Slf4j
+public class DjbPropertyHolder {
+
+ private static volatile DjbProperty instance = new DjbProperty();
+ private static volatile Function injector;
+
+ private DjbPropertyHolder() {
+ // 유틸리티 클래스
+ }
+
+ /**
+ * 현재 DjbProperty 인스턴스를 반환합니다.
+ */
+ public static DjbProperty get() {
+ return instance;
+ }
+
+ /**
+ * 초기화 함수를 등록하고 최초 로딩을 수행합니다.
+ * eapim-admin 부팅 시 MonitoringContextImpl.init()에서 호출됩니다.
+ *
+ * @param injectorFn DjbProperty를 DB에서 로딩하는 함수 (DjbPropertyInjector::inject)
+ */
+ public static void initialize(Function injectorFn) {
+ injector = injectorFn;
+ reload();
+ log.info("DjbPropertyHolder 초기화 완료");
+ }
+
+ /**
+ * DB에서 프로퍼티를 다시 로딩합니다.
+ * MonitoringContext.refresh() 호출 시 함께 호출됩니다.
+ */
+ public static void reload() {
+ if (injector != null) {
+ try {
+ instance = injector.apply(new DjbProperty());
+ log.info("DjbProperty reload 완료");
+ } catch (Exception e) {
+ log.error("DjbProperty reload 실패: {}", e.getMessage(), e);
+ }
+ } else {
+ log.debug("DjbPropertyHolder: injector가 설정되지 않음 (테스트 환경일 수 있음)");
+ }
+ }
+
+ /**
+ * 테스트용 - 직접 인스턴스를 설정합니다.
+ */
+ public static void setForTest(DjbProperty testProperty) {
+ instance = testProperty;
+ log.debug("DjbProperty 테스트 인스턴스 설정");
+ }
+
+ /**
+ * 테스트용 - 기본값으로 초기화합니다.
+ */
+ public static void resetForTest() {
+ instance = new DjbProperty();
+ injector = null;
+ log.debug("DjbPropertyHolder 테스트 초기화");
+ }
+}
diff --git a/src/main/java/com/eactive/ext/kjb/util/KjbPropertyInjector.java b/src/main/java/com/eactive/eai/rms/ext/djb/common/DjbPropertyInjector.java
similarity index 76%
rename from src/main/java/com/eactive/ext/kjb/util/KjbPropertyInjector.java
rename to src/main/java/com/eactive/eai/rms/ext/djb/common/DjbPropertyInjector.java
index 8d2dfb5..3d61fb5 100644
--- a/src/main/java/com/eactive/ext/kjb/util/KjbPropertyInjector.java
+++ b/src/main/java/com/eactive/eai/rms/ext/djb/common/DjbPropertyInjector.java
@@ -1,10 +1,8 @@
-package com.eactive.ext.kjb.util;
+package com.eactive.eai.rms.ext.djb.common;
import com.eactive.eai.rms.data.entity.man.monitoringProperty.MonitoringProperty;
import com.eactive.eai.rms.data.entity.man.monitoringProperty.MonitoringPropertyId;
import com.eactive.eai.rms.data.entity.man.monitoringProperty.service.MonitoringPropertyService;
-import com.eactive.ext.kjb.common.KjbProperty;
-import com.eactive.ext.kjb.common.KjbPropertyValue;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@@ -12,52 +10,49 @@ import java.lang.reflect.Field;
import java.util.Optional;
@Slf4j
-public class KjbPropertyInjector {
+public class DjbPropertyInjector {
private final MonitoringPropertyService monitoringPropertyService;
private final String groupId;
- public KjbPropertyInjector(MonitoringPropertyService monitoringPropertyService, String groupId) {
+ public DjbPropertyInjector(MonitoringPropertyService monitoringPropertyService, String groupId) {
this.monitoringPropertyService = monitoringPropertyService;
this.groupId = groupId;
}
/**
- * KjbProperty의 URL 값들이 설정되어 있는지 확인
- * @param property 검사할 KjbProperty 객체
+ * DjbProperty의 URL 값들이 설정되어 있는지 확인
+ * @param property 검사할 DjbProperty 객체
* @return URL 값들이 모두 설정되어 있으면 true
*/
- public boolean isUrlConfigured(KjbProperty property) {
+ public boolean isUrlConfigured(DjbProperty property) {
if (property == null) return false;
- // 주요 URL 값들 중 하나라도 설정되어 있으면 true
- return StringUtils.isNotEmpty(property.getEaiBatchUrl())
- || StringUtils.isNotEmpty(property.getUmsHostUrl())
- || StringUtils.isNotEmpty(property.getObpUrl());
+ return StringUtils.isNotEmpty(property.getApiAllowIpList());
}
/**
* URL 값이 비어있을 경우 DB에서 재로딩 시도
- * @param property 기존 KjbProperty 객체
- * @return 재로딩된 KjbProperty 객체 (재로딩 실패 시 기존 객체 반환)
+ * @param property 기존 DjbProperty 객체
+ * @return 재로딩된 DjbProperty 객체 (재로딩 실패 시 기존 객체 반환)
*/
- public KjbProperty reloadIfUrlEmpty(KjbProperty property) {
+ public DjbProperty reloadIfUrlEmpty(DjbProperty property) {
if (property == null) {
- return inject(new KjbProperty());
+ return inject(new DjbProperty());
}
if (!isUrlConfigured(property)) {
- log.info("KjbProperty URL 값이 비어있어 DB에서 재로딩 시도");
+ log.info("DjbProperty URL 값이 비어있어 DB에서 재로딩 시도");
try {
- KjbProperty reloaded = inject(new KjbProperty());
+ DjbProperty reloaded = inject(new DjbProperty());
if (isUrlConfigured(reloaded)) {
- log.info("KjbProperty 재로딩 성공");
+ log.info("DjbProperty 재로딩 성공");
return reloaded;
} else {
- log.warn("KjbProperty 재로딩 후에도 URL 값이 비어있음");
+ log.warn("DjbProperty 재로딩 후에도 URL 값이 비어있음");
}
} catch (Exception e) {
- log.error("KjbProperty 재로딩 실패: {}", e.getMessage(), e);
+ log.error("DjbProperty 재로딩 실패: {}", e.getMessage(), e);
}
}
@@ -68,7 +63,7 @@ public class KjbPropertyInjector {
Class> clazz = property.getClass();
for (Field field : clazz.getDeclaredFields()) {
- KjbPropertyValue anno = field.getAnnotation(KjbPropertyValue.class);
+ DjbPropertyValue anno = field.getAnnotation(DjbPropertyValue.class);
if (anno != null) {
String key = anno.key();
diff --git a/src/main/java/com/eactive/eai/rms/ext/djb/common/DjbPropertyValue.java b/src/main/java/com/eactive/eai/rms/ext/djb/common/DjbPropertyValue.java
new file mode 100644
index 0000000..a1e6393
--- /dev/null
+++ b/src/main/java/com/eactive/eai/rms/ext/djb/common/DjbPropertyValue.java
@@ -0,0 +1,14 @@
+package com.eactive.eai.rms.ext.djb.common;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface DjbPropertyValue {
+ String key();
+ String defaultValue() default "";
+ String description() default "";
+}
diff --git a/src/main/java/com/eactive/eai/rms/ext/kjb/smsauth/SmsAuthController.java b/src/main/java/com/eactive/eai/rms/ext/djb/smsauth/SmsAuthController.java
similarity index 99%
rename from src/main/java/com/eactive/eai/rms/ext/kjb/smsauth/SmsAuthController.java
rename to src/main/java/com/eactive/eai/rms/ext/djb/smsauth/SmsAuthController.java
index 73aa5ba..cf49ca4 100644
--- a/src/main/java/com/eactive/eai/rms/ext/kjb/smsauth/SmsAuthController.java
+++ b/src/main/java/com/eactive/eai/rms/ext/djb/smsauth/SmsAuthController.java
@@ -1,4 +1,4 @@
-package com.eactive.eai.rms.ext.kjb.smsauth;
+package com.eactive.eai.rms.ext.djb.smsauth;
import com.eactive.apim.portal.user.entity.UserInfo;
import com.eactive.eai.rms.common.interceptor.InterceptorSkipController;
diff --git a/src/main/java/com/eactive/eai/rms/ext/kjb/smsauth/SmsAuthDto.java b/src/main/java/com/eactive/eai/rms/ext/djb/smsauth/SmsAuthDto.java
similarity index 95%
rename from src/main/java/com/eactive/eai/rms/ext/kjb/smsauth/SmsAuthDto.java
rename to src/main/java/com/eactive/eai/rms/ext/djb/smsauth/SmsAuthDto.java
index 3944255..ac89b23 100644
--- a/src/main/java/com/eactive/eai/rms/ext/kjb/smsauth/SmsAuthDto.java
+++ b/src/main/java/com/eactive/eai/rms/ext/djb/smsauth/SmsAuthDto.java
@@ -1,4 +1,4 @@
-package com.eactive.eai.rms.ext.kjb.smsauth;
+package com.eactive.eai.rms.ext.djb.smsauth;
import lombok.AllArgsConstructor;
import lombok.Builder;
diff --git a/src/main/java/com/eactive/eai/rms/ext/kjb/smsauth/SmsAuthService.java b/src/main/java/com/eactive/eai/rms/ext/djb/smsauth/SmsAuthService.java
similarity index 94%
rename from src/main/java/com/eactive/eai/rms/ext/kjb/smsauth/SmsAuthService.java
rename to src/main/java/com/eactive/eai/rms/ext/djb/smsauth/SmsAuthService.java
index 187784e..73ef754 100644
--- a/src/main/java/com/eactive/eai/rms/ext/kjb/smsauth/SmsAuthService.java
+++ b/src/main/java/com/eactive/eai/rms/ext/djb/smsauth/SmsAuthService.java
@@ -1,4 +1,4 @@
-package com.eactive.eai.rms.ext.kjb.smsauth;
+package com.eactive.eai.rms.ext.djb.smsauth;
import java.security.SecureRandom;
import java.time.LocalDateTime;
@@ -13,11 +13,9 @@ import org.springframework.stereotype.Service;
import com.eactive.apim.portal.template.entity.MessageCode;
import com.eactive.apim.portal.user.entity.UserInfo;
import com.eactive.eai.rms.common.login.LoginVo;
+import com.eactive.eai.rms.ext.djb.common.DjbProperty;
+import com.eactive.eai.rms.ext.djb.common.DjbPropertyHolder;
import com.eactive.eai.rms.ext.djb.ums.UmsManager;
-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.KjbUmsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -46,13 +44,11 @@ public class SmsAuthService {
private final UmsManager ums;
- private static KjbProperty getProperty() {
- return KjbPropertyHolder.get();
+ private static DjbProperty getProperty() {
+ return DjbPropertyHolder.get();
}
- private KjbUmsService getUmsService() {
- return KjbUmsService.getInstance();
- }
+
/**
* SMS 인증이 필요한지 확인
@@ -86,7 +82,7 @@ public class SmsAuthService {
* 인증번호 생성
*/
public String generateAuthCode() {
- KjbProperty prop = getProperty();
+ DjbProperty prop = getProperty();
String mode = prop.getSmsAuthMode();
if (MODE_FIXED.equalsIgnoreCase(mode)) {
@@ -113,7 +109,7 @@ public class SmsAuthService {
HashMap params = new HashMap();
params.put("authNumber", authCode);
params.put("userName", userInfo.getUsername());
-log.debug("\n\n\nDDDDDDDDD" + userInfo.toString());
+
ums.send(userInfo, MessageCode.ADMIN_VERIFICATION_MOBILEPHONE, params);
return true;
} catch (Exception e) {
diff --git a/src/main/java/com/eactive/eai/rms/ext/djb/ums/service/UmsService.java b/src/main/java/com/eactive/eai/rms/ext/djb/ums/service/UmsService.java
index df534fa..8d1062c 100644
--- a/src/main/java/com/eactive/eai/rms/ext/djb/ums/service/UmsService.java
+++ b/src/main/java/com/eactive/eai/rms/ext/djb/ums/service/UmsService.java
@@ -248,15 +248,15 @@ public class UmsService {
// 이메일 데이터
EmailDataVO dataVO = new EmailDataVO();
- dataVO.setUms_evnt_id(""); // UMS이벤트ID(필수)
+ dataVO.setUms_evnt_id(""); // TODO: UMS이벤트ID(필수)
dataVO.setSnd_dman_dt(jsonData[0]);
dataVO.setSnd_dman_id("");
dataVO.setSnd_dman_sno("1");
dataVO.setEmail_titl(messageRequest.getSubject()); // 메일제목
- dataVO.setCstno(""); // 고객번호(필수)
- dataVO.setSendr_emaddr(""); // 발신자 이메일
- dataVO.setSendr_nm(""); // 발신자 이름
- dataVO.setSndbk_emaddr(""); // 리턴 이메일
+ dataVO.setCstno(""); // TODO: 고객번호(필수)
+ dataVO.setSendr_emaddr(""); // TODO: 발신자 이메일
+ dataVO.setSendr_nm(""); // TODO: 발신자 이름
+ dataVO.setSndbk_emaddr(""); // TODO: 리턴 이메일
dataVO.setRecvr_emaddr(messageRequest.getEmail()); // 수신자 이메일(필수)
dataVO.setRecvr_nm(messageRequest.getUsername()); // 수신자명(필수)
dataVO.setTmplt_mpng_info(messageRequest.getMessage()); // 탬플릿매핑정보
@@ -266,8 +266,8 @@ public class UmsService {
dataVO.setBzwk_cd(BZWK_DVCD); // 업무구분코드
dataVO.setSub_bzwk_cd(SUB_BZWK_CD); // 업무세부코드
dataVO.setSys_dvcd(SYS_DVCD);
- dataVO.setTx_dt(jsonData[0]); //거래일자
- dataVO.setTx_tktm(jsonData[1].substring(0,6)); //거래시간
+ dataVO.setTx_dt(jsonData[0]); // 거래일자
+ dataVO.setTx_tktm(jsonData[1].substring(0,6)); // 거래시간
List dataList = new ArrayList();
dataList.add(dataVO);
diff --git a/src/main/java/com/eactive/eai/rms/ext/kjb/sso/SsoController.java b/src/main/java/com/eactive/eai/rms/ext/kjb/sso/SsoController.java
index 5789cb3..a042729 100644
--- a/src/main/java/com/eactive/eai/rms/ext/kjb/sso/SsoController.java
+++ b/src/main/java/com/eactive/eai/rms/ext/kjb/sso/SsoController.java
@@ -14,9 +14,9 @@ import com.eactive.eai.rms.data.entity.man.user.UserRoleId;
import com.eactive.eai.rms.data.entity.man.user.UserRoleService;
import com.eactive.eai.rms.data.entity.man.user.UserServiceTypeService;
import com.eactive.eai.rms.onl.apim.masking.MaskingUtils;
-import com.eactive.ext.kjb.common.KjbProperty;
-import com.eactive.ext.kjb.common.KjbPropertyHolder;
-import com.eactive.ext.kjb.sso.KjbSsoModule;
+//import com.eactive.ext.kjb.common.KjbProperty;
+//import com.eactive.ext.kjb.common.KjbPropertyHolder;
+//import com.eactive.ext.kjb.sso.KjbSsoModule;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
@@ -52,108 +52,108 @@ public class SsoController implements InterceptorSkipController {
this.mainController = mainController;
}
- private KjbSsoModule getSsoModule() {
- return KjbSsoModule.getInstance();
- }
+// private KjbSsoModule getSsoModule() {
+// return KjbSsoModule.getInstance();
+// }
+//
+// private KjbProperty getProperty() {
+// return KjbPropertyHolder.get();
+// }
- private KjbProperty getProperty() {
- return KjbPropertyHolder.get();
- }
-
- @RequestMapping(value = "/sso/login.do")
- public String login(HttpServletRequest req, HttpServletResponse res,
- @RequestParam(name = "UURL", required = false) String uurl) throws Exception {
- HttpSession session = req.getSession();
- String ssoId = getSsoModule().getSsoId(req);
-
- log.debug("ssoId : {}", ssoId);
- log.debug("uurl : {}", uurl);
-
- // 디버깅용 쿠키 목록 출력
- if (log.isDebugEnabled()) {
- Cookie[] cookies = req.getCookies();
- if (cookies == null || cookies.length == 0) {
- log.debug("No cookies");
- } else {
- for (Cookie c : cookies) {
- log.debug("Cookie[{}] : Domain={}, Path={}",
- c.getName(), c.getDomain(), c.getPath());
- }
- }
- }
-
- if (StringUtils.isEmpty(uurl)) {
- uurl = getSsoModule().getAscpUrl();
- log.debug("UURL is empty, set to ASCP URL");
- log.debug("uurl : {}", uurl);
- }
-
- if (ssoId == null) {
- getSsoModule().goLoginPage(res, uurl);
- return null;
- } else {
- // EAM 세션 검증
- String retCode = getSsoModule().getEamSessionCheck(req, res);
- log.debug("retCode : {}", retCode);
-
- log.debug("Property - sso.ignore_validation = {}", getProperty().isSsoIgnoreValidation());
- if (!getProperty().isSsoIgnoreValidation() && !"0".equalsIgnoreCase(retCode)) {
- // SSO 검증 실패 시 에러 메시지 설정 및 로그인 페이지로 이동
- log.warn("SSO 검증 실패 - retCode: {}, ssoId: {}", retCode, ssoId);
- session.setAttribute("resultMsg", "SSO 로그인을 실패 하였습니다. (오류코드: " + retCode + ") 다른 로그인 방식을 시도 하세요");
- return "redirect:/loginForm.do";
- }
-
- if (StringUtils.isEmpty(ssoId)) {
- session.setAttribute("resultMsg", "SSO 인증 정보를 획득하지 못했습니다.");
- return "redirect:/loginForm.do";
- }
-
- if (getProperty().isSsoSyncInfo()) {
- // 기본 정보
- Properties info = getSsoModule().getUserInfos(ssoId);
- // 확장 정보
- Properties extendedInfo = getSsoModule().getUserExFields(ssoId);
-
- // 필수 필드 검증
- try {
- validateRequiredFields(info, extendedInfo);
- } catch (IllegalStateException e) {
- log.warn("SSO 필수 필드 검증 실패: {}", e.getMessage());
- session.setAttribute("resultMsg", e.getMessage());
- return "redirect:/loginForm.do";
- }
-
- // 사용자 정보 로깅 (개인정보 마스킹 처리)
- String userId = info.getProperty("USERID");
- String name = info.getProperty("NAME");
- String email = info.getProperty("EMAIL");
- String cellPhoneNo = extendedInfo != null ? extendedInfo.getProperty("CELLPHONENO") : null;
-
- log.info("SSO 로그인 시도 - userId: {}", userId);
- log.debug("SSO 사용자 정보 - userId: {}, name: {}, phone: {}, email: {}",
- userId,
- MaskingUtils.maskName(name),
- MaskingUtils.maskPhoneNumber(cellPhoneNo),
- MaskingUtils.maskEmailId(email));
-
- // 사용자 생성 또는 업데이트
- UserInfo userInfo = findOrCreateUser(info, extendedInfo);
-
- // 로그인 세션 설정 (MainController 위임)
- log.info("SSO 로그인 성공 - userId: {}", userId);
- return mainController.setupSsoLoginSession(req, userInfo);
- } else {
- // 동기화 비활성화 모드: 기존 사용자는 업데이트 없이, 신규 사용자는 최소 정보로 생성
- log.info("SSO 동기화 비활성화 모드로 로그인 처리 - ssoId: {}", ssoId);
-
- UserInfo userInfo = findOrCreateUserWithoutSync(ssoId);
-
- log.info("SSO 로그인 성공 (동기화 비활성화 모드) - userId: {}", ssoId);
- return mainController.setupSsoLoginSession(req, userInfo);
- }
- }
- }
+// @RequestMapping(value = "/sso/login.do")
+// public String login(HttpServletRequest req, HttpServletResponse res,
+// @RequestParam(name = "UURL", required = false) String uurl) throws Exception {
+// HttpSession session = req.getSession();
+// String ssoId = getSsoModule().getSsoId(req);
+//
+// log.debug("ssoId : {}", ssoId);
+// log.debug("uurl : {}", uurl);
+//
+// // 디버깅용 쿠키 목록 출력
+// if (log.isDebugEnabled()) {
+// Cookie[] cookies = req.getCookies();
+// if (cookies == null || cookies.length == 0) {
+// log.debug("No cookies");
+// } else {
+// for (Cookie c : cookies) {
+// log.debug("Cookie[{}] : Domain={}, Path={}",
+// c.getName(), c.getDomain(), c.getPath());
+// }
+// }
+// }
+//
+// if (StringUtils.isEmpty(uurl)) {
+// uurl = getSsoModule().getAscpUrl();
+// log.debug("UURL is empty, set to ASCP URL");
+// log.debug("uurl : {}", uurl);
+// }
+//
+// if (ssoId == null) {
+// getSsoModule().goLoginPage(res, uurl);
+// return null;
+// } else {
+// // EAM 세션 검증
+// String retCode = getSsoModule().getEamSessionCheck(req, res);
+// log.debug("retCode : {}", retCode);
+//
+// log.debug("Property - sso.ignore_validation = {}", getProperty().isSsoIgnoreValidation());
+// if (!getProperty().isSsoIgnoreValidation() && !"0".equalsIgnoreCase(retCode)) {
+// // SSO 검증 실패 시 에러 메시지 설정 및 로그인 페이지로 이동
+// log.warn("SSO 검증 실패 - retCode: {}, ssoId: {}", retCode, ssoId);
+// session.setAttribute("resultMsg", "SSO 로그인을 실패 하였습니다. (오류코드: " + retCode + ") 다른 로그인 방식을 시도 하세요");
+// return "redirect:/loginForm.do";
+// }
+//
+// if (StringUtils.isEmpty(ssoId)) {
+// session.setAttribute("resultMsg", "SSO 인증 정보를 획득하지 못했습니다.");
+// return "redirect:/loginForm.do";
+// }
+//
+// if (getProperty().isSsoSyncInfo()) {
+// // 기본 정보
+// Properties info = getSsoModule().getUserInfos(ssoId);
+// // 확장 정보
+// Properties extendedInfo = getSsoModule().getUserExFields(ssoId);
+//
+// // 필수 필드 검증
+// try {
+// validateRequiredFields(info, extendedInfo);
+// } catch (IllegalStateException e) {
+// log.warn("SSO 필수 필드 검증 실패: {}", e.getMessage());
+// session.setAttribute("resultMsg", e.getMessage());
+// return "redirect:/loginForm.do";
+// }
+//
+// // 사용자 정보 로깅 (개인정보 마스킹 처리)
+// String userId = info.getProperty("USERID");
+// String name = info.getProperty("NAME");
+// String email = info.getProperty("EMAIL");
+// String cellPhoneNo = extendedInfo != null ? extendedInfo.getProperty("CELLPHONENO") : null;
+//
+// log.info("SSO 로그인 시도 - userId: {}", userId);
+// log.debug("SSO 사용자 정보 - userId: {}, name: {}, phone: {}, email: {}",
+// userId,
+// MaskingUtils.maskName(name),
+// MaskingUtils.maskPhoneNumber(cellPhoneNo),
+// MaskingUtils.maskEmailId(email));
+//
+// // 사용자 생성 또는 업데이트
+// UserInfo userInfo = findOrCreateUser(info, extendedInfo);
+//
+// // 로그인 세션 설정 (MainController 위임)
+// log.info("SSO 로그인 성공 - userId: {}", userId);
+// return mainController.setupSsoLoginSession(req, userInfo);
+// } else {
+// // 동기화 비활성화 모드: 기존 사용자는 업데이트 없이, 신규 사용자는 최소 정보로 생성
+// log.info("SSO 동기화 비활성화 모드로 로그인 처리 - ssoId: {}", ssoId);
+//
+// UserInfo userInfo = findOrCreateUserWithoutSync(ssoId);
+//
+// log.info("SSO 로그인 성공 (동기화 비활성화 모드) - userId: {}", ssoId);
+// return mainController.setupSsoLoginSession(req, userInfo);
+// }
+// }
+// }
/**
* 필수 필드 검증
diff --git a/src/main/java/com/eactive/eai/rms/onl/apim/obp/ObpGwMetricManService.java b/src/main/java/com/eactive/eai/rms/onl/apim/obp/ObpGwMetricManService.java
index a815b2c..b007940 100644
--- a/src/main/java/com/eactive/eai/rms/onl/apim/obp/ObpGwMetricManService.java
+++ b/src/main/java/com/eactive/eai/rms/onl/apim/obp/ObpGwMetricManService.java
@@ -1,5 +1,23 @@
package com.eactive.eai.rms.onl.apim.obp;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
import com.eactive.apim.portal.apprequest.entity.AppRequest;
import com.eactive.apim.portal.apprequest.repository.AppRequestRepository;
import com.eactive.apim.portal.obp.entity.ObpGwMetric;
@@ -10,18 +28,7 @@ import com.eactive.eai.rms.common.util.CommonUtil;
import com.eactive.eai.rms.data.entity.onl.apim.obp.ObpGwMetricJpaDAO;
import com.eactive.eai.rms.data.entity.onl.apim.obp.ObpGwMetricService;
import com.eactive.eai.rms.data.entity.onl.apim.obp.ObpGwMetricVO;
-import com.eactive.ext.kjb.common.KjbPropertyHolder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.dao.DataIntegrityViolationException;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.time.temporal.ChronoUnit;
-import java.util.*;
-import java.util.stream.Collectors;
+import com.eactive.eai.rms.ext.djb.common.DjbPropertyHolder;
/**
* ObpGwMetric Man Service - 비즈니스 로직
@@ -328,7 +335,7 @@ public class ObpGwMetricManService extends BaseService {
DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.MONITORING));
// KjbProperty에서 pageSize 읽기
- Integer pageSize = KjbPropertyHolder.get().getApiGwMetricPageSize();
+ Integer pageSize = DjbPropertyHolder.get().getApiGwMetricPageSize();
if (pageSize == null) {
pageSize = 10000; // 기본값 (null 안전 처리)
}
diff --git a/src/main/java/com/eactive/eai/rms/onl/apim/service/IpAuthenticationService.java b/src/main/java/com/eactive/eai/rms/onl/apim/service/IpAuthenticationService.java
index 753c7eb..b433aa1 100644
--- a/src/main/java/com/eactive/eai/rms/onl/apim/service/IpAuthenticationService.java
+++ b/src/main/java/com/eactive/eai/rms/onl/apim/service/IpAuthenticationService.java
@@ -1,11 +1,13 @@
package com.eactive.eai.rms.onl.apim.service;
-import com.eactive.eai.util.IpUtil;
-import com.eactive.ext.kjb.common.KjbPropertyHolder;
-import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
+import com.eactive.eai.rms.ext.djb.common.DjbPropertyHolder;
+import com.eactive.eai.util.IpUtil;
+
+import lombok.extern.slf4j.Slf4j;
+
/**
* IP 화이트리스트 인증 서비스
*
@@ -113,7 +115,7 @@ public class IpAuthenticationService {
*/
private String loadWhitelistFromDb() {
try {
- String whitelist = KjbPropertyHolder.get().getApiAllowIpList();
+ String whitelist = DjbPropertyHolder.get().getApiAllowIpList();
if (StringUtils.isBlank(whitelist)) {
log.warn("IP whitelist property is empty");
return "";