diff --git a/kjb-docs/README.md b/kjb-docs/README.md index 010efe9..d42120d 100644 --- a/kjb-docs/README.md +++ b/kjb-docs/README.md @@ -3,4 +3,7 @@ ## 커스텀 항목 ### 포탈 Property (EMS 프로퍼티) - `disable_features.user_email_verify' == true - 이메일 인증 기능 비활성화(회원 가입시 이메일 인증은 한걸로 처리) \ No newline at end of file + 이메일 인증 기능 비활성화(회원 가입시 이메일 인증은 한걸로 처리) + +### 디비 접속 방법 Direct -> JNDI 로 변경 +- 은행 내부 환경에선 모두 JNDI 사용하기 때문에 서버환경에서 동작하는 profile 내 application.yaml 에서 디비 접속 정보 삭제 \ No newline at end of file diff --git a/src/main/java/com/eactive/apim/portal/config/BaseDatasourceConfiguration.java b/src/main/java/com/eactive/apim/portal/config/BaseDatasourceConfiguration.java new file mode 100644 index 0000000..dd17a85 --- /dev/null +++ b/src/main/java/com/eactive/apim/portal/config/BaseDatasourceConfiguration.java @@ -0,0 +1,126 @@ +package com.eactive.apim.portal.config; + +import com.eactive.eai.data.jpa.BaseRepositoryImpl; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import javax.annotation.PostConstruct; +import javax.naming.NamingException; +import javax.sql.DataSource; + +import com.zaxxer.hikari.HikariDataSource; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.core.env.Environment; +import org.springframework.data.domain.AuditorAware; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jndi.JndiObjectFactoryBean; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; + +@Slf4j +public class BaseDatasourceConfiguration { + private final Environment env; + + + public BaseDatasourceConfiguration(Environment env) { + this.env = env; + } + + + protected DataSource jndiLookup(String jndiName) throws NamingException { + JndiObjectFactoryBean bean = new JndiObjectFactoryBean(); + bean.setJndiName(jndiName); + bean.setProxyInterface(DataSource.class); + bean.afterPropertiesSet(); + return (DataSource) bean.getObject(); + } + + protected DataSource createDataSource(DatasourceProperty prop) { + HikariDataSource dataSource = new HikariDataSource(); + dataSource.setJdbcUrl(prop.getJdbcUrl()); + dataSource.setUsername(prop.getUsername()); + dataSource.setPassword(prop.getPassword()); + dataSource.setDriverClassName(prop.getDriverClassName()); + + // 커넥션 풀 설정 + dataSource.setMinimumIdle(5); + dataSource.setMaximumPoolSize(10); + dataSource.setIdleTimeout(60000); // 60s + dataSource.setConnectionTimeout(30000); // 30s + dataSource.setConnectionTestQuery("SELECT 1 FROM DUAL"); + return dataSource; + } + + protected LocalContainerEntityManagerFactoryBean createEntityManagerFactory(EntityManagerFactoryBuilder builder, + DataSource dataSource, + DatasourceProperty prop) { + String persistenceUnit; + + HashMap properties = new HashMap<>(); + //public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings 참고 + properties.put("hibernate.dialect", prop.getHibernateDialect()); + properties.put("hibernate.connection.handling_mode", "DELAYED_ACQUISITION_AND_RELEASE_AFTER_TRANSACTION"); + properties.put("hibernate.transaction.jta.platform", "org.hibernate.engine.transaction.jta.platform.internal.AtomikosJtaPlatform"); + properties.put("hibernate.physical_naming_strategy", prop.getHibernatePhysicalNamingStrategy()); + properties.put("hibernate.default_schema", prop.getSchema()); + properties.put("javax.persistence.validation.mode", "none"); + properties.put("javax.persistence.transactionType", "JTA"); + + if (prop instanceof EmsDatasourceProperty) { + persistenceUnit = "portal"; + + properties.put("hibernate.cache.use_second_level_cache", "false"); + properties.put("hibernate.cache.use_query_cache", "false"); + properties.put("hibernate.connection.autocommit", "false"); + + // Envers properties org.hibernate.envers.configuration.EnversSettings 참고 + properties.put("org.hibernate.envers.audit_strategy", "org.hibernate.envers.strategy.internal.ValidityAuditStrategy"); + properties.put("org.hibernate.envers.audit_table_suffix", "_AUD"); + properties.put("org.hibernate.envers.default_schema", "audit"); + properties.put("org.hibernate.envers.global_with_modified_flag", "true"); + properties.put("org.hibernate.envers.revision_field_name", "REVISION"); + properties.put("org.hibernate.envers.revision_type_field_name", "REVISION_TYPE"); + properties.put("org.hibernate.envers.revision_number_field_name", "id"); + properties.put("org.hibernate.envers.store_data_at_delete", "true"); + } else { + persistenceUnit = "gateway"; + } + + // 개발 환경용 + if (env.matchesProfiles("dev", "local")) { + properties.put("hibernate.hbm2ddl.auto", "validate"); + } + + + // DDL 생성용 + if (env.matchesProfiles("ddl_generate")) { + log.warn("Spring profile 내 ddl_generate 지정됨 / 로컬 개발용"); + + String filePath = "D:\\kjb-logs\\devSvr99\\portal-schema_ddl-" + + DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss").format(LocalDateTime.now()) + ".sql"; + + properties.put("hibernate.hbm2ddl.auto", "validate"); + properties.put("javax.persistence.schema-generation.create-source", "metadata"); + properties.put("javax.persistence.schema-generation.scripts.action", "update"); +// properties.put("javax.persistence.schema-generation.scripts.action", "create"); + properties.put("javax.persistence.schema-generation.scripts.create-target", filePath); + + log.info("DDL script 생성 : {}", filePath); + } + + return builder + .dataSource(dataSource) + .packages(prop.getEntityPackage()) + .persistenceUnit(persistenceUnit) + .properties(properties) + .build(); + } +} diff --git a/src/main/java/com/eactive/apim/portal/config/DatasourceProperty.java b/src/main/java/com/eactive/apim/portal/config/DatasourceProperty.java new file mode 100644 index 0000000..eb0585b --- /dev/null +++ b/src/main/java/com/eactive/apim/portal/config/DatasourceProperty.java @@ -0,0 +1,22 @@ +package com.eactive.apim.portal.config; + +import lombok.Data; + +@Data +public class DatasourceProperty { + private String jndiName; + private String schema; + + // EntityManager 용 + private String hibernateDialect; + private String hibernatePhysicalNamingStrategy; + private String entityPackage; + + // 로컬개발 또는 직접 접속용 + private String jdbcUrl; + private String driverClassName; + private String username; + private String password; + + +} diff --git a/src/main/java/com/eactive/apim/portal/config/EmsDatasourceProperties.java b/src/main/java/com/eactive/apim/portal/config/EmsDatasourceProperty.java similarity index 51% rename from src/main/java/com/eactive/apim/portal/config/EmsDatasourceProperties.java rename to src/main/java/com/eactive/apim/portal/config/EmsDatasourceProperty.java index 4cde3f5..66d4daa 100644 --- a/src/main/java/com/eactive/apim/portal/config/EmsDatasourceProperties.java +++ b/src/main/java/com/eactive/apim/portal/config/EmsDatasourceProperty.java @@ -1,19 +1,13 @@ package com.eactive.apim.portal.config; import lombok.Data; +import lombok.EqualsAndHashCode; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; +@EqualsAndHashCode(callSuper = true) @Component @ConfigurationProperties(prefix = "ems.datasource") @Data -public class EmsDatasourceProperties { - - private String url; - private String username; - private String password; - private String databaseName; - private String serverName; - private String schema; - private int portNumber; +public class EmsDatasourceProperty extends DatasourceProperty { } diff --git a/src/main/java/com/eactive/apim/portal/config/GatewayDataSourceProperties.java b/src/main/java/com/eactive/apim/portal/config/GatewayDataSourceProperty.java similarity index 51% rename from src/main/java/com/eactive/apim/portal/config/GatewayDataSourceProperties.java rename to src/main/java/com/eactive/apim/portal/config/GatewayDataSourceProperty.java index f85eb1c..fdaff83 100644 --- a/src/main/java/com/eactive/apim/portal/config/GatewayDataSourceProperties.java +++ b/src/main/java/com/eactive/apim/portal/config/GatewayDataSourceProperty.java @@ -1,19 +1,13 @@ package com.eactive.apim.portal.config; import lombok.Data; +import lombok.EqualsAndHashCode; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; +@EqualsAndHashCode(callSuper = true) @Data @Component @ConfigurationProperties(prefix = "gateway.datasource") -public class GatewayDataSourceProperties { - - private String url; - private String username; - private String password; - private String databaseName; - private String serverName; - private String schema; - private int portNumber; +public class GatewayDataSourceProperty extends DatasourceProperty { } diff --git a/src/main/java/com/eactive/apim/portal/config/GatewayDatasourceConfiguration.java b/src/main/java/com/eactive/apim/portal/config/GatewayDatasourceConfiguration.java new file mode 100644 index 0000000..940e5ba --- /dev/null +++ b/src/main/java/com/eactive/apim/portal/config/GatewayDatasourceConfiguration.java @@ -0,0 +1,124 @@ +package com.eactive.apim.portal.config; + +import com.eactive.eai.data.jpa.BaseRepositoryImpl; +import com.zaxxer.hikari.HikariDataSource; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.core.env.Environment; +import org.springframework.data.domain.AuditorAware; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jndi.JndiObjectFactoryBean; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; + +import javax.annotation.PostConstruct; +import javax.naming.NamingException; +import javax.sql.DataSource; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; + +@Configuration +@EntityScan(basePackages = {"com.eactive.apim.gateway"}) +@EnableJpaRepositories(basePackages = "com.eactive.apim.gateway", repositoryBaseClass = BaseRepositoryImpl.class, entityManagerFactoryRef = "gatewayEntityManagerFactory") +@EnableJpaAuditing(auditorAwareRef = "auditorProvider") +@Slf4j +public class GatewayDatasourceConfiguration extends BaseDatasourceConfiguration { + private final Environment env; + private final GatewayDataSourceProperty gatewayProp; + private final EmsDatasourceProperty emsProp; + + + public GatewayDatasourceConfiguration(Environment env, GatewayDataSourceProperty gatewayProp, EmsDatasourceProperty emsProp) { + super(env); + + this.env = env; + this.gatewayProp = gatewayProp; + this.emsProp = emsProp; + } + + + @PostConstruct + public void init() { + if (StringUtils.isEmpty(gatewayProp.getSchema()) || StringUtils.isEmpty(emsProp.getSchema())) { + log.error("Profile property 'schema' is empty. Please check your configuration."); + throw new IllegalArgumentException("GatewayDataSourceProperties schema is empty. Please check your configuration."); + } + + + // EMS 파라미터와 호환되도록 프로퍼티 명칭 설정 + System.setProperty("eai.tableowner", emsProp.getSchema()); + } + + + @Bean + public DataSource gatewayDataSource(GatewayDataSourceProperty gatewayProp) { + // JNDI 이용 + if (StringUtils.isNotEmpty(gatewayProp.getJndiName())) { + try { + return this.jndiLookup(gatewayProp.getJndiName()); + } catch (NamingException e) { + log.warn("JNDI lookup failed.", e); + } + } + + log.info("개발환경을 위해 JNDI 대신 직접 DB 접속 시도"); + + // JNDI 실패시 직접 접속 이용 + if (StringUtils.isEmpty(gatewayProp.getJdbcUrl())) { + throw new IllegalArgumentException("DB 접속을 위한 JNDI 또는 서버 접속 정보가 설정되어 있지 않음"); + } + + return createDataSource(gatewayProp); + } + + @Primary + @Bean + public DataSource portalDataSource(EmsDatasourceProperty emsProp) { + // JNDI 이용 + if (StringUtils.isNotEmpty(emsProp.getJndiName())) { + try { + return this.jndiLookup(emsProp.getJndiName()); + } catch (NamingException e) { + log.warn("JNDI lookup failed.", e); + } + } + + log.info("개발환경을 위해 JNDI 대신 직접 DB 접속 시도"); + + // JNDI 실패시 직접 접속 이용 + if (StringUtils.isEmpty(emsProp.getJdbcUrl())) { + throw new IllegalArgumentException("DB 접속을 위한 JNDI 또는 서버 접속 정보가 설정되어 있지 않음"); + } + + return createDataSource(emsProp); + } + + @Bean(name = "gatewayEntityManagerFactory") + public LocalContainerEntityManagerFactoryBean gatewayEntityManagerFactory( + EntityManagerFactoryBuilder builder, + @Qualifier("gatewayDataSource") DataSource dataSource, + GatewayDataSourceProperty gatewayProp) { + return createEntityManagerFactory(builder, dataSource, gatewayProp); + } + + @Primary + @Bean(name = "entityManagerFactory") + public LocalContainerEntityManagerFactoryBean entityManagerFactory( + EntityManagerFactoryBuilder builder, + @Qualifier("gatewayDataSource") DataSource dataSource, + EmsDatasourceProperty emsProp) { + return createEntityManagerFactory(builder, dataSource, emsProp); + } + + @Bean + public AuditorAware auditorProvider() { + return new AuditorAwareImpl(); + } +} diff --git a/src/main/java/com/eactive/apim/portal/config/PortalConfigGatewayDatasource.java b/src/main/java/com/eactive/apim/portal/config/PortalConfigGatewayDatasource.java deleted file mode 100644 index d857187..0000000 --- a/src/main/java/com/eactive/apim/portal/config/PortalConfigGatewayDatasource.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.eactive.apim.portal.config; - -import com.eactive.eai.data.jpa.BaseRepositoryImpl; -import java.util.HashMap; -import java.util.Properties; -import javax.annotation.PostConstruct; -import javax.sql.DataSource; - -import com.zaxxer.hikari.HikariDataSource; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean; -import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.jpa.repository.config.EnableJpaAuditing; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; - -@Configuration -@EnableJpaRepositories(basePackages = {"com.eactive.apim.gateway"}, - repositoryBaseClass = BaseRepositoryImpl.class, - entityManagerFactoryRef = "gatewayEntityManagerFactory") -@EnableJpaAuditing(auditorAwareRef = "auditorProvider") -@Slf4j -public class PortalConfigGatewayDatasource { - - @Autowired - private GatewayDataSourceProperties gatewayDataSourceProperties; - - - @PostConstruct - public void init() { - if (StringUtils.isEmpty(gatewayDataSourceProperties.getSchema())) { - log.error("Profile property 'schema' is empty. Please check your configuration."); - throw new IllegalArgumentException("GatewayDataSourceProperties schema is empty. Please check your configuration."); - } - } - - -// @Bean -// public DataSource gatewayDataSource() { -// AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean(); -// dataSource.setBeanName("gatewayDataSource"); -// dataSource.setUniqueResourceName("gatewayDataSource"); -// dataSource.setMinPoolSize(5); -// dataSource.setMaxPoolSize(10); -// dataSource.setMaxIdleTime(60); // seconds -// dataSource.setBorrowConnectionTimeout(30); // seconds -// dataSource.setTestQuery("SELECT 1 FROM DUAL"); -// dataSource.setMaintenanceInterval(60); -// dataSource.setXaDataSourceClassName("oracle.jdbc.xa.client.OracleXADataSource"); -// -// Properties xaProperties = new Properties(); -// String url = String.format("jdbc:oracle:thin:@//%s:%d/%s", -// gatewayDataSourceProperties.getServerName(), // HOST -// gatewayDataSourceProperties.getPortNumber(), // PORT -// gatewayDataSourceProperties.getDatabaseName()); // SERVICE_NAME 또는 SID -// // SID를 사용하는 경우: "jdbc:oracle:thin:@host:port:SID" -// -// xaProperties.setProperty("URL", url); -// xaProperties.setProperty("user", gatewayDataSourceProperties.getUsername()); -// xaProperties.setProperty("password", gatewayDataSourceProperties.getPassword()); -// -// dataSource.setXaProperties(xaProperties); -// return dataSource; -// } - - @Bean - public DataSource gatewayDataSource() { - HikariDataSource dataSource = new HikariDataSource(); - - String url = String.format("jdbc:oracle:thin:@//%s:%d/%s", - gatewayDataSourceProperties.getServerName(), // HOST - gatewayDataSourceProperties.getPortNumber(), // PORT - gatewayDataSourceProperties.getDatabaseName()); // SERVICE_NAME 또는 SID - - dataSource.setJdbcUrl(url); - dataSource.setUsername(gatewayDataSourceProperties.getUsername()); - dataSource.setPassword(gatewayDataSourceProperties.getPassword()); - dataSource.setDriverClassName("oracle.jdbc.OracleDriver"); - - // 커넥션 풀 세팅 - dataSource.setMinimumIdle(5); - dataSource.setMaximumPoolSize(10); - dataSource.setIdleTimeout(60000); // 60초 - dataSource.setConnectionTimeout(30000); // 30초 - dataSource.setConnectionTestQuery("SELECT 1 FROM DUAL"); - - return dataSource; - } - - @Bean(name = "gatewayEntityManagerFactory") - public LocalContainerEntityManagerFactoryBean gatewayEntityManagerFactory( - EntityManagerFactoryBuilder builder, - @Qualifier("gatewayDataSource") DataSource dataSource) { - HashMap properties = new HashMap<>(); - //public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings 참고 - properties.put("hibernate.dialect", "org.hibernate.dialect.Oracle12cDialect"); - properties.put("hibernate.connection.handling_mode", "DELAYED_ACQUISITION_AND_RELEASE_AFTER_TRANSACTION"); - properties.put("hibernate.transaction.jta.platform", "org.hibernate.engine.transaction.jta.platform.internal.AtomikosJtaPlatform"); - properties.put("hibernate.physical_naming_strategy", "com.eactive.apim.portal.common.entity.CustomPhysicalNamingStrategy"); - properties.put("hibernate.default_schema", gatewayDataSourceProperties.getSchema()); - properties.put("javax.persistence.validation.mode", "none"); - properties.put("javax.persistence.transactionType", "JTA"); - - return builder - .dataSource(dataSource) - .packages("com.eactive.eai.data.entity.onl") - .persistenceUnit("gateway") - .properties(properties) - .build(); - } -} diff --git a/src/main/java/com/eactive/apim/portal/config/PortalConfigPortalDatasource.java b/src/main/java/com/eactive/apim/portal/config/PortalConfigPortalDatasource.java deleted file mode 100644 index 730d3ae..0000000 --- a/src/main/java/com/eactive/apim/portal/config/PortalConfigPortalDatasource.java +++ /dev/null @@ -1,192 +0,0 @@ -package com.eactive.apim.portal.config; - -import com.eactive.eai.data.jpa.BaseRepositoryImpl; -import com.zaxxer.hikari.HikariDataSource; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.domain.EntityScan; -import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import org.springframework.core.env.Environment; -import org.springframework.data.domain.AuditorAware; -import org.springframework.data.envers.repository.support.EnversRevisionRepositoryFactoryBean; -import org.springframework.data.jpa.repository.config.EnableJpaAuditing; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; - -import javax.annotation.PostConstruct; -import javax.sql.DataSource; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.HashMap; - -/** - * @author Sungpil Hyun - * @version : 1.0 - * - *
- * << 개정이력(Modification Information) >>
- *
- *   수정일              수정자               수정내용
- *  -------------  ------------   ---------------------
- *
- * 
- * @ClassName : PortalConfigAppDatasource.java - * @Description : DataSource 설정 - * @since : - */ -@Configuration -@EnableJpaRepositories(basePackages = "com.eactive.apim.portal", - repositoryBaseClass = BaseRepositoryImpl.class, - repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class) -@EntityScan(basePackages = "com.eactive.apim.portal") -@EnableJpaAuditing(auditorAwareRef = "auditorProvider") -@Slf4j -public class PortalConfigPortalDatasource { - private final EmsDatasourceProperties emsDatasourceProperties; - private final Environment env; - - - public PortalConfigPortalDatasource(EmsDatasourceProperties emsDatasourceProperties, Environment env) { - this.emsDatasourceProperties = emsDatasourceProperties; - this.env = env; - } - - - @PostConstruct - public void checkProfile() { - if (StringUtils.isEmpty(emsDatasourceProperties.getSchema())) { - log.error("Profile property 'schema' is empty. Please check your configuration."); - throw new IllegalArgumentException("'ems.datasource.schema' is not configured."); - } - - - // EMS 파라미터와 호환되도록 프로퍼티 명칭 설정 - System.setProperty("eai.tableowner", emsDatasourceProperties.getSchema()); - } - - @Primary - @Bean - public DataSource portalDataSource() { -// AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean(); -// dataSource.setBeanName("portalDataSource"); -// dataSource.setUniqueResourceName("portalDataSource"); -// dataSource.setMinPoolSize(5); -// dataSource.setMaxPoolSize(10); -// dataSource.setMaxIdleTime(60); // seconds -// dataSource.setBorrowConnectionTimeout(30); // seconds -// dataSource.setTestQuery("SELECT 1 FROM DUAL"); -// dataSource.setMaintenanceInterval(60); -// dataSource.setXaDataSourceClassName("oracle.jdbc.xa.client.OracleXADataSource"); -// -// Properties xaProperties = new Properties(); -// String url = String.format("jdbc:oracle:thin:@//%s:%d/%s", -// emsDatasourceProperties.getServerName(), // HOST -// emsDatasourceProperties.getPortNumber(), // PORT -// emsDatasourceProperties.getDatabaseName()); // SERVICE_NAME 또는 SID -// // SID를 사용하는 경우: "jdbc:oracle:thin:@host:port:SID" -// -// xaProperties.setProperty("URL", url); -// xaProperties.setProperty("user", emsDatasourceProperties.getUsername()); -// xaProperties.setProperty("password", emsDatasourceProperties.getPassword()); -// -// dataSource.setXaProperties(xaProperties); -// return dataSource; - - HikariDataSource dataSource = new HikariDataSource(); - - String url = String.format("jdbc:oracle:thin:@//%s:%d/%s", - emsDatasourceProperties.getServerName(), // HOST - emsDatasourceProperties.getPortNumber(), // PORT - emsDatasourceProperties.getDatabaseName()); // SERVICE_NAME 또는 SID - - dataSource.setJdbcUrl(url); - dataSource.setUsername(emsDatasourceProperties.getUsername()); - dataSource.setPassword(emsDatasourceProperties.getPassword()); - dataSource.setDriverClassName("oracle.jdbc.OracleDriver"); - - // 커넥션 풀 설정 - dataSource.setMinimumIdle(5); - dataSource.setMaximumPoolSize(10); - dataSource.setIdleTimeout(60000); // 60s - dataSource.setConnectionTimeout(30000); // 30s - dataSource.setConnectionTestQuery("SELECT 1 FROM DUAL"); - - return dataSource; - } - - @Primary - @Bean(name = "entityManagerFactory") - public LocalContainerEntityManagerFactoryBean entityManagerFactory( - EntityManagerFactoryBuilder builder, - @Qualifier("portalDataSource") DataSource dataSource) { - HashMap properties = new HashMap<>(); - //public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings 참고 - properties.put("hibernate.cache.use_second_level_cache", "false"); - properties.put("hibernate.cache.use_query_cache", "false"); - properties.put("hibernate.connection.autocommit", "false"); - properties.put("hibernate.connection.handling_mode", "DELAYED_ACQUISITION_AND_RELEASE_AFTER_TRANSACTION"); - properties.put("hibernate.connection.provider_disables_autocommit", "true"); - properties.put("hibernate.dialect", "org.hibernate.dialect.Oracle12cDialect"); - properties.put("hibernate.format_sql", "true"); - properties.put("hibernate.physical_naming_strategy", "com.eactive.apim.portal.common.entity.CustomPhysicalNamingStrategy"); - -// properties.put("hibernate.show_sql", "true"); - properties.put("hibernate.transaction.jta.platform", "org.hibernate.engine.transaction.jta.platform.internal.AtomikosJtaPlatform"); - properties.put("hibernate.use_sql_comments", "true"); - properties.put("hibernate.default_schema", emsDatasourceProperties.getSchema()); - properties.put("javax.persistence.validation.mode", "none"); - properties.put("javax.persistence.transactionType", "JTA"); - - - // Envers properties org.hibernate.envers.configuration.EnversSettings 참고 - properties.put("org.hibernate.envers.audit_strategy", "org.hibernate.envers.strategy.internal.ValidityAuditStrategy"); - properties.put("org.hibernate.envers.audit_table_suffix", "_AUD"); - properties.put("org.hibernate.envers.default_schema", "audit"); - properties.put("org.hibernate.envers.global_with_modified_flag", "true"); - properties.put("org.hibernate.envers.revision_field_name", "REVISION"); - properties.put("org.hibernate.envers.revision_type_field_name", "REVISION_TYPE"); - properties.put("org.hibernate.envers.revision_number_field_name", "id"); - properties.put("org.hibernate.envers.store_data_at_delete", "true"); - - // 개발 환경용 - if (env.matchesProfiles("dev", "local")) { - properties.put("hibernate.hbm2ddl.auto", "validate"); - } - - - // DDL 생성용 - if (env.matchesProfiles("ddl_generate")) { - log.warn("Spring profile 내 ddl_generate 지정됨 / 로컬 개발용"); - - String filePath = "D:\\kjb-logs\\devSvr99\\portal-schema_ddl-" + - DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss").format(LocalDateTime.now()) + ".sql"; - - properties.put("hibernate.hbm2ddl.auto", "validate"); - properties.put("javax.persistence.schema-generation.create-source", "metadata"); - properties.put("javax.persistence.schema-generation.scripts.action", "update"); -// properties.put("javax.persistence.schema-generation.scripts.action", "create"); - properties.put("javax.persistence.schema-generation.scripts.create-target", filePath); - - log.info("DDL script 생성 : {}", filePath); - } - - - return builder - .dataSource(dataSource) - .packages("com.eactive.apim.portal") - .persistenceUnit("portal") - .properties(properties) - .build(); - } - - @Bean - public AuditorAware auditorProvider() { - return new AuditorAwareImpl(); - } - -} diff --git a/src/main/java/com/eactive/apim/portal/config/PortalDatasourceConfiguration.java b/src/main/java/com/eactive/apim/portal/config/PortalDatasourceConfiguration.java new file mode 100644 index 0000000..f13c8bf --- /dev/null +++ b/src/main/java/com/eactive/apim/portal/config/PortalDatasourceConfiguration.java @@ -0,0 +1,92 @@ +package com.eactive.apim.portal.config; + +import com.eactive.eai.data.jpa.BaseRepositoryImpl; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.core.env.Environment; +import org.springframework.data.domain.AuditorAware; +import org.springframework.data.envers.repository.support.EnversRevisionRepositoryFactoryBean; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; + +import javax.annotation.PostConstruct; +import javax.naming.NamingException; +import javax.sql.DataSource; + +@Configuration +@EntityScan(basePackages = {"com.eactive.apim.portal"}) +@EnableJpaRepositories(basePackages = "com.eactive.apim.portal", + repositoryBaseClass = BaseRepositoryImpl.class, + repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class) +@EnableJpaAuditing(auditorAwareRef = "auditorProvider") +@Slf4j +public class PortalDatasourceConfiguration extends BaseDatasourceConfiguration { + private final Environment env; + private final GatewayDataSourceProperty gatewayProp; + private final EmsDatasourceProperty emsProp; + + + public PortalDatasourceConfiguration(Environment env, GatewayDataSourceProperty gatewayProp, EmsDatasourceProperty emsProp) { + super(env); + + this.env = env; + this.gatewayProp = gatewayProp; + this.emsProp = emsProp; + } + + + @PostConstruct + public void init() { + if (StringUtils.isEmpty(gatewayProp.getSchema()) || StringUtils.isEmpty(emsProp.getSchema())) { + log.error("Profile property 'schema' is empty. Please check your configuration."); + throw new IllegalArgumentException("GatewayDataSourceProperties schema is empty. Please check your configuration."); + } + + + // EMS 파라미터와 호환되도록 프로퍼티 명칭 설정 + System.setProperty("eai.tableowner", emsProp.getSchema()); + } + + @Primary + @Bean + public DataSource portalDataSource(EmsDatasourceProperty emsProp) { + // JNDI 이용 + if (StringUtils.isNotEmpty(emsProp.getJndiName())) { + try { + return this.jndiLookup(emsProp.getJndiName()); + } catch (NamingException e) { + log.warn("JNDI lookup failed.", e); + } + } + + log.info("개발환경을 위해 JNDI 대신 직접 DB 접속 시도"); + + // JNDI 실패시 직접 접속 이용 + if (StringUtils.isEmpty(emsProp.getJdbcUrl())) { + throw new IllegalArgumentException("DB 접속을 위한 JNDI 또는 서버 접속 정보가 설정되어 있지 않음"); + } + + return createDataSource(emsProp); + } + + @Primary + @Bean(name = "entityManagerFactory") + public LocalContainerEntityManagerFactoryBean entityManagerFactory( + EntityManagerFactoryBuilder builder, + @Qualifier("portalDataSource") DataSource dataSource, + EmsDatasourceProperty emsProp) { + return createEntityManagerFactory(builder, dataSource, emsProp); + } + + @Bean + public AuditorAware auditorProvider() { + return new AuditorAwareImpl(); + } +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 6160cf7..9b9da74 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -18,22 +18,6 @@ spring: thymeleaf: cache: false -ems: - datasource: - serverName: 192.168.240.177 - portNumber: 1599 - databaseName: DAPM - username: EMSAPP - password: EMSAPP123! - -gateway: - datasource: - serverName: 192.168.240.177 - portNumber: 1599 - databaseName: DAPM - username: AGWAPP - password: AGWAPP123! - portal: auth-virtual-code: 654321 diff --git a/src/main/resources/application-gf63.yml b/src/main/resources/application-gf63.yml index 236bd33..db76a24 100644 --- a/src/main/resources/application-gf63.yml +++ b/src/main/resources/application-gf63.yml @@ -19,21 +19,18 @@ spring: ems: datasource: - serverName: 192.168.240.177 - portNumber: 1599 - databaseName: DAPM + jdbc-url: jdbc:oracle:thin:@//192.168.240.177:1599/DAPM + driver-class-name: oracle.jdbc.OracleDriver username: EMSAPP password: EMSAPP123! - schema: EMSADM + gateway: datasource: - serverName: 192.168.240.177 - portNumber: 1599 - databaseName: DAPM + jdbc-url: jdbc:oracle:thin:@//192.168.240.177:1599/DAPM + driver-class-name: oracle.jdbc.OracleDriver username: AGWAPP password: AGWAPP123! - schema: AGWADM portal: logging: diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index b7d2fc5..1532889 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -18,22 +18,6 @@ spring: thymeleaf: cache: false -ems: - datasource: - serverName: 172.24.80.145 - portNumber: 3319 - databaseName: apims - username: api_app - password: Papiapp*17 - -gateway: - datasource: - serverName: 172.24.80.145 - portNumber: 3319 - databaseName: apigw - username: api_app - password: Papiapp*17 - proxy: targets: stg: http://inter-dapiwas01.k-bank.com:7090/monitoring diff --git a/src/main/resources/application-stage.yml b/src/main/resources/application-stage.yml index c3ac31a..0cd16bd 100644 --- a/src/main/resources/application-stage.yml +++ b/src/main/resources/application-stage.yml @@ -15,27 +15,9 @@ spring: thymeleaf: cache: false -ems: - datasource: - serverName: 192.168.240.177 - portNumber: 1599 - databaseName: DAPM - username: EMSAPP - password: EMSAPP123! - schema: EMSADM - portal: auth-virtual-code: 654321 -gateway: - datasource: - serverName: 192.168.240.177 - portNumber: 1599 - databaseName: DAPM - username: AGWAPP - password: AGWAPP123! - schema: AGWADM - #proxy: # targets: # stg: http://inter-dapiwas01.k-bank.com:7090/monitoring diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 8737519..eeb173b 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -50,6 +50,25 @@ security: sample-code-path: classpath:/templates/sample_code + +ems: + datasource: + jndi-name: jdbc/dsOBP_AGW + schema: EMSADM + + hibernate-dialect: org.hibernate.dialect.Oracle12cDialect + hibernate-physical-naming-strategy: com.eactive.apim.portal.common.entity.CustomPhysicalNamingStrategy + entity-package: com.eactive.apim.portal + +gateway: + datasource: + jndi-name: jdbc/dsOBP_AGW + schema: AGWADM + + hibernate-dialect: org.hibernate.dialect.Oracle12cDialect + hibernate-physical-naming-strategy: com.eactive.apim.portal.common.entity.CustomPhysicalNamingStrategy + entity-package: com.eactive.eai.data.entity.onl + portal: logging: log-path: /Log/App/eapim/ diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml index b6f814b..0a29ad7 100644 --- a/src/main/resources/logback-spring.xml +++ b/src/main/resources/logback-spring.xml @@ -77,21 +77,21 @@ - + - + - + - - + + - - + + - - - + + + @@ -104,7 +104,7 @@ > - +