From 61560797307aa20ca8bdb1c84b0bf55e85c30bd3 Mon Sep 17 00:00:00 2001 From: aazizali Date: Wed, 21 May 2025 19:08:32 -0400 Subject: [PATCH 01/12] Update Hibernate cache dependency and configuration Signed-off-by: aazizali --- data/synapse-data-postgres/pom.xml | 2 +- .../data/postgres/config/BasePostgresDataConfig.java | 3 ++- pom.xml | 7 +++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/data/synapse-data-postgres/pom.xml b/data/synapse-data-postgres/pom.xml index 344abd0f9..b30e7ec89 100644 --- a/data/synapse-data-postgres/pom.xml +++ b/data/synapse-data-postgres/pom.xml @@ -59,7 +59,7 @@ org.hibernate - hibernate-ehcache + hibernate-jcache diff --git a/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java b/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java index 0dfaedb16..9420e3dd9 100644 --- a/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java +++ b/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java @@ -79,8 +79,9 @@ private Properties additionalHibernateSpringProperties() { properties.setProperty("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql")); properties.setProperty("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql")); properties.setProperty("spring.datasource.initialization-mode", environment.getRequiredProperty("spring.datasource.initialization-mode")); + properties.setProperty("hibernate.cache.use_second_level_cache", "true"); properties.setProperty("hibernate.cache.use_query_cache", "true"); - properties.setProperty("hibernate.cache.provider_class", "org.ehcache.hibernate.EhCacheProvider"); + properties.setProperty("hibernate.cache.provider_class", "org.ehcache.jsr107.EhcacheCachingProvider"); return properties; } diff --git a/pom.xml b/pom.xml index 733b1a7b2..3912235e2 100644 --- a/pom.xml +++ b/pom.xml @@ -639,14 +639,13 @@ org.ehcache ehcache - 3.10.8 + jakarta - org.hibernate - hibernate-ehcache - 5.6.15.Final + hibernate-jcache + 6.6.15.Final org.hibernate From 792e5c4d9d9c31f37f563c1cd7bf99fcca442b01 Mon Sep 17 00:00:00 2001 From: aazizali Date: Wed, 21 May 2025 20:09:51 -0400 Subject: [PATCH 02/12] Remove classifier for ehcache dependency in pom.xml Signed-off-by: aazizali --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3912235e2..46d8f2532 100644 --- a/pom.xml +++ b/pom.xml @@ -639,7 +639,6 @@ org.ehcache ehcache - jakarta From 0a3713d3d718f4cac0d15aecd5ba14cb7f6931ea Mon Sep 17 00:00:00 2001 From: aazizali Date: Thu, 22 May 2025 11:56:18 -0400 Subject: [PATCH 03/12] Add CacheManager bean configuration for Ehcache integration Signed-off-by: aazizali --- .../config/BasePostgresDataConfig.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java b/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java index 9420e3dd9..048995a5b 100644 --- a/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java +++ b/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java @@ -14,6 +14,11 @@ package io.americanexpress.synapse.data.postgres.config; import com.zaxxer.hikari.HikariDataSource; +import org.ehcache.config.CacheConfiguration; +import org.ehcache.config.builders.CacheConfigurationBuilder; +import org.ehcache.config.builders.ExpiryPolicyBuilder; +import org.ehcache.config.builders.ResourcePoolsBuilder; +import org.ehcache.jsr107.Eh107Configuration; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; @@ -24,7 +29,11 @@ import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.annotation.EnableTransactionManagement; +import javax.cache.CacheManager; +import javax.cache.Caching; +import javax.cache.spi.CachingProvider; import javax.sql.DataSource; +import java.time.Duration; import java.util.Properties; /** @@ -99,6 +108,25 @@ public LocalContainerEntityManagerFactoryBean entityManagerFactory() { return entityManagerFactoryBean; } + @Bean + public CacheManager cacheManager() { + CachingProvider cachingProvider = Caching.getCachingProvider(); + CacheManager cacheManager = cachingProvider.getCacheManager(); + + CacheConfiguration cacheConfiguration = + CacheConfigurationBuilder.newCacheConfigurationBuilder( + Object.class, Object.class, ResourcePoolsBuilder.heap(1000)) + .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMinutes(10))) + .build(); + + javax.cache.configuration.Configuration configuration = + Eh107Configuration.fromEhcacheCacheConfiguration(cacheConfiguration); + + cacheManager.createCache("defaultCache", configuration); + + return cacheManager; + } + /** * Set the packages to Scan property to the entityManagerFactory. * From a654e7c936946c9dc0254acb987b3cb08a32a46b Mon Sep 17 00:00:00 2001 From: aazizali Date: Thu, 22 May 2025 13:35:24 -0400 Subject: [PATCH 04/12] Update Ehcache dependency version to 3.10.8 Signed-off-by: aazizali --- pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 46d8f2532..d9ba4a27f 100644 --- a/pom.xml +++ b/pom.xml @@ -638,7 +638,8 @@ org.ehcache - ehcache + ehcache + 3.10.8 From 259461af4702f972b6f119102928304979db7333 Mon Sep 17 00:00:00 2001 From: aazizali Date: Thu, 22 May 2025 15:26:21 -0400 Subject: [PATCH 05/12] Fix indentation in Ehcache dependency declaration in pom.xml Signed-off-by: aazizali --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d9ba4a27f..72bda930d 100644 --- a/pom.xml +++ b/pom.xml @@ -638,7 +638,7 @@ org.ehcache - ehcache + ehcache 3.10.8 From 5a7fef4fe4840f2d296c620a11a7ba9d74a3c783 Mon Sep 17 00:00:00 2001 From: aazizali Date: Thu, 22 May 2025 15:30:34 -0400 Subject: [PATCH 06/12] Enhance CacheManager configuration with dynamic properties for cache name, heap size, and expiry Signed-off-by: aazizali --- .../data/postgres/config/BasePostgresDataConfig.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java b/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java index 048995a5b..68456866e 100644 --- a/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java +++ b/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java @@ -20,6 +20,7 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.jsr107.Eh107Configuration; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; @@ -109,20 +110,25 @@ public LocalContainerEntityManagerFactoryBean entityManagerFactory() { } @Bean + @ConditionalOnMissingBean(CacheManager.class) public CacheManager cacheManager() { + String cacheName = environment.getProperty("synapse.second_level_cache_name", "default"); + long entries = environment.getProperty("synapse.second_level_cache_heap_entries", Long.class, 1000L); + int minutes = environment.getProperty("synapse.second_level_cache_expiry_in_minutes", Integer.class, 10); + CachingProvider cachingProvider = Caching.getCachingProvider(); CacheManager cacheManager = cachingProvider.getCacheManager(); CacheConfiguration cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder( - Object.class, Object.class, ResourcePoolsBuilder.heap(1000)) - .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMinutes(10))) + Object.class, Object.class, ResourcePoolsBuilder.heap(entries)) + .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMinutes(minutes))) .build(); javax.cache.configuration.Configuration configuration = Eh107Configuration.fromEhcacheCacheConfiguration(cacheConfiguration); - cacheManager.createCache("defaultCache", configuration); + cacheManager.createCache(cacheName, configuration); return cacheManager; } From aa5791d87ee1b63e56bc07c2d1ee078c66cfc513 Mon Sep 17 00:00:00 2001 From: aazizali Date: Thu, 22 May 2025 16:11:51 -0400 Subject: [PATCH 07/12] Refactor BasePostgresDataConfig to improve constructor visibility and rename cacheManager method for clarity Signed-off-by: aazizali --- .../data/postgres/config/BasePostgresDataConfig.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java b/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java index 68456866e..596bb8236 100644 --- a/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java +++ b/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java @@ -19,7 +19,6 @@ import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.jsr107.Eh107Configuration; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; @@ -51,7 +50,6 @@ public abstract class BasePostgresDataConfig { /** * Used to acquire environment variables. */ - @Autowired protected Environment environment; /** @@ -59,7 +57,7 @@ public abstract class BasePostgresDataConfig { * * @param environment the environment */ - public BasePostgresDataConfig(Environment environment) { + protected BasePostgresDataConfig(Environment environment) { this.environment = environment; } @@ -111,7 +109,7 @@ public LocalContainerEntityManagerFactoryBean entityManagerFactory() { @Bean @ConditionalOnMissingBean(CacheManager.class) - public CacheManager cacheManager() { + public CacheManager configureSecondLevelCacheManager() { String cacheName = environment.getProperty("synapse.second_level_cache_name", "default"); long entries = environment.getProperty("synapse.second_level_cache_heap_entries", Long.class, 1000L); int minutes = environment.getProperty("synapse.second_level_cache_expiry_in_minutes", Integer.class, 10); @@ -136,7 +134,7 @@ public CacheManager cacheManager() { /** * Set the packages to Scan property to the entityManagerFactory. * - * @param entityManagerFactoryBean + * @param entityManagerFactoryBean the entity manager factory bean */ protected abstract void setPackagesToScan(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean); } From 5ff60c38dd95b25554233557c5e8a24b6a96d560 Mon Sep 17 00:00:00 2001 From: aazizali Date: Mon, 26 May 2025 15:32:43 -0400 Subject: [PATCH 08/12] Add Ehcache configuration file and update BasePostgresDataConfig for cache URI Signed-off-by: aazizali --- .../config/BasePostgresDataConfig.java | 35 +------------------ .../src/main/resources/ehcache.xml | 19 ++++++++++ 2 files changed, 20 insertions(+), 34 deletions(-) create mode 100644 data/synapse-data-postgres/src/main/resources/ehcache.xml diff --git a/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java b/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java index 596bb8236..47d2b0f64 100644 --- a/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java +++ b/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java @@ -14,12 +14,6 @@ package io.americanexpress.synapse.data.postgres.config; import com.zaxxer.hikari.HikariDataSource; -import org.ehcache.config.CacheConfiguration; -import org.ehcache.config.builders.CacheConfigurationBuilder; -import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.config.builders.ResourcePoolsBuilder; -import org.ehcache.jsr107.Eh107Configuration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; @@ -29,11 +23,7 @@ import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.annotation.EnableTransactionManagement; -import javax.cache.CacheManager; -import javax.cache.Caching; -import javax.cache.spi.CachingProvider; import javax.sql.DataSource; -import java.time.Duration; import java.util.Properties; /** @@ -90,6 +80,7 @@ private Properties additionalHibernateSpringProperties() { properties.setProperty("hibernate.cache.use_second_level_cache", "true"); properties.setProperty("hibernate.cache.use_query_cache", "true"); properties.setProperty("hibernate.cache.provider_class", "org.ehcache.jsr107.EhcacheCachingProvider"); + properties.setProperty("hibernate.javax.cache.uri", environment.getProperty("hibernate.javax.cache.uri", "classpath:ehcache.xml")); return properties; } @@ -107,30 +98,6 @@ public LocalContainerEntityManagerFactoryBean entityManagerFactory() { return entityManagerFactoryBean; } - @Bean - @ConditionalOnMissingBean(CacheManager.class) - public CacheManager configureSecondLevelCacheManager() { - String cacheName = environment.getProperty("synapse.second_level_cache_name", "default"); - long entries = environment.getProperty("synapse.second_level_cache_heap_entries", Long.class, 1000L); - int minutes = environment.getProperty("synapse.second_level_cache_expiry_in_minutes", Integer.class, 10); - - CachingProvider cachingProvider = Caching.getCachingProvider(); - CacheManager cacheManager = cachingProvider.getCacheManager(); - - CacheConfiguration cacheConfiguration = - CacheConfigurationBuilder.newCacheConfigurationBuilder( - Object.class, Object.class, ResourcePoolsBuilder.heap(entries)) - .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMinutes(minutes))) - .build(); - - javax.cache.configuration.Configuration configuration = - Eh107Configuration.fromEhcacheCacheConfiguration(cacheConfiguration); - - cacheManager.createCache(cacheName, configuration); - - return cacheManager; - } - /** * Set the packages to Scan property to the entityManagerFactory. * diff --git a/data/synapse-data-postgres/src/main/resources/ehcache.xml b/data/synapse-data-postgres/src/main/resources/ehcache.xml new file mode 100644 index 000000000..31b34641c --- /dev/null +++ b/data/synapse-data-postgres/src/main/resources/ehcache.xml @@ -0,0 +1,19 @@ + + + + + + + + + 5 + + 100 + + \ No newline at end of file From a92fc64473d8b2eda58782b99686337157bdf3af Mon Sep 17 00:00:00 2001 From: aazizali Date: Tue, 27 May 2025 09:27:59 -0400 Subject: [PATCH 09/12] Fix missing newline at end of ehcache.xml file Signed-off-by: aazizali --- data/synapse-data-postgres/src/main/resources/ehcache.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/synapse-data-postgres/src/main/resources/ehcache.xml b/data/synapse-data-postgres/src/main/resources/ehcache.xml index 31b34641c..c7c93f9ce 100644 --- a/data/synapse-data-postgres/src/main/resources/ehcache.xml +++ b/data/synapse-data-postgres/src/main/resources/ehcache.xml @@ -16,4 +16,4 @@ 100 - \ No newline at end of file + From d1c49ac3f5dcf76651f24e9831bc9a37d91c425d Mon Sep 17 00:00:00 2001 From: aazizali Date: Tue, 27 May 2025 09:32:41 -0400 Subject: [PATCH 10/12] Remove version numbers for ehcache and hibernate-jcache dependencies in pom.xml Signed-off-by: aazizali --- pom.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pom.xml b/pom.xml index 72bda930d..f7e6a849d 100644 --- a/pom.xml +++ b/pom.xml @@ -639,13 +639,11 @@ org.ehcache ehcache - 3.10.8 org.hibernate hibernate-jcache - 6.6.15.Final org.hibernate From 16252ae774047fafe0e10a103993ad06127bcb30 Mon Sep 17 00:00:00 2001 From: aazizali Date: Tue, 27 May 2025 13:17:05 -0400 Subject: [PATCH 11/12] Add JCacheRegionFactory property to Hibernate cache configuration Signed-off-by: aazizali --- .../synapse/data/postgres/config/BasePostgresDataConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java b/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java index 47d2b0f64..74c2d0c6d 100644 --- a/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java +++ b/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java @@ -80,6 +80,7 @@ private Properties additionalHibernateSpringProperties() { properties.setProperty("hibernate.cache.use_second_level_cache", "true"); properties.setProperty("hibernate.cache.use_query_cache", "true"); properties.setProperty("hibernate.cache.provider_class", "org.ehcache.jsr107.EhcacheCachingProvider"); + properties.setProperty("hibernate.cache.region.factory_class", "org.hibernate.cache.jcache.internal.JCacheRegionFactory" ); properties.setProperty("hibernate.javax.cache.uri", environment.getProperty("hibernate.javax.cache.uri", "classpath:ehcache.xml")); return properties; } From 71a9360637c66f6c5064a6d3aa5e57f1a9a2e15c Mon Sep 17 00:00:00 2001 From: aazizali Date: Wed, 11 Jun 2025 14:35:47 -0400 Subject: [PATCH 12/12] Update Hibernate cache configuration and add integration tests for second-level cache Signed-off-by: aazizali --- data/synapse-data-postgres/pom.xml | 8 +- .../config/BasePostgresDataConfig.java | 6 +- .../src/main/resources/ehcache.xml | 5 +- .../config/BasePostgresDataConfigTest.java | 122 ++++++++++++++++++ .../postgres/config/DataSampleConfig.java | 48 +++++++ .../synapse/data/postgres/entity/Product.java | 46 +++++++ .../src/test/resources/data.sql | 10 ++ .../src/test/resources/ehcache.xml | 19 +++ .../resources/kocho-application.properties | 20 +++ .../src/test/resources/schema.sql | 23 ++++ pom.xml | 5 +- 11 files changed, 304 insertions(+), 8 deletions(-) create mode 100644 data/synapse-data-postgres/src/test/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfigTest.java create mode 100644 data/synapse-data-postgres/src/test/java/io/americanexpress/synapse/data/postgres/config/DataSampleConfig.java create mode 100644 data/synapse-data-postgres/src/test/java/io/americanexpress/synapse/data/postgres/entity/Product.java create mode 100644 data/synapse-data-postgres/src/test/resources/data.sql create mode 100644 data/synapse-data-postgres/src/test/resources/ehcache.xml create mode 100644 data/synapse-data-postgres/src/test/resources/kocho-application.properties create mode 100644 data/synapse-data-postgres/src/test/resources/schema.sql diff --git a/data/synapse-data-postgres/pom.xml b/data/synapse-data-postgres/pom.xml index b30e7ec89..3eacf963e 100644 --- a/data/synapse-data-postgres/pom.xml +++ b/data/synapse-data-postgres/pom.xml @@ -56,9 +56,10 @@ org.ehcache ehcache + jakarta - org.hibernate + org.hibernate.orm hibernate-jcache @@ -66,6 +67,11 @@ jakarta.persistence jakarta.persistence-api + + org.springframework.boot + spring-boot-starter-test + test + diff --git a/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java b/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java index 74c2d0c6d..f1596a9ff 100644 --- a/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java +++ b/data/synapse-data-postgres/src/main/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfig.java @@ -30,6 +30,7 @@ * BasePostgresDataConfig class is used to hold the common configuration for all data-postgres modules. * * @author Gabriel Jimenez + * @author Aziz Ali */ @Configuration @EnableTransactionManagement @@ -62,7 +63,6 @@ public DataSource dataSource() { HikariDataSource dataSource = DataSourceBuilder.create().type(HikariDataSource.class).build(); dataSource.setSchema(environment.getRequiredProperty("spring.jpa.properties.hibernate.default_schema")); dataSource.setLeakDetectionThreshold(2000); - dataSource.setDataSourceProperties(additionalHibernateSpringProperties()); return dataSource; } @@ -81,7 +81,8 @@ private Properties additionalHibernateSpringProperties() { properties.setProperty("hibernate.cache.use_query_cache", "true"); properties.setProperty("hibernate.cache.provider_class", "org.ehcache.jsr107.EhcacheCachingProvider"); properties.setProperty("hibernate.cache.region.factory_class", "org.hibernate.cache.jcache.internal.JCacheRegionFactory" ); - properties.setProperty("hibernate.javax.cache.uri", environment.getProperty("hibernate.javax.cache.uri", "classpath:ehcache.xml")); + properties.setProperty("hibernate.javax.cache.uri", + environment.getProperty("hibernate.javax.cache.uri", "classpath://ehcache.xml")); return properties; } @@ -95,6 +96,7 @@ public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); entityManagerFactoryBean.setDataSource(dataSource()); entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); + entityManagerFactoryBean.setJpaProperties(additionalHibernateSpringProperties()); setPackagesToScan(entityManagerFactoryBean); return entityManagerFactoryBean; } diff --git a/data/synapse-data-postgres/src/main/resources/ehcache.xml b/data/synapse-data-postgres/src/main/resources/ehcache.xml index c7c93f9ce..049053b56 100644 --- a/data/synapse-data-postgres/src/main/resources/ehcache.xml +++ b/data/synapse-data-postgres/src/main/resources/ehcache.xml @@ -9,11 +9,10 @@ - - 5 + 10 - 100 + 1000 diff --git a/data/synapse-data-postgres/src/test/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfigTest.java b/data/synapse-data-postgres/src/test/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfigTest.java new file mode 100644 index 000000000..3fd143512 --- /dev/null +++ b/data/synapse-data-postgres/src/test/java/io/americanexpress/synapse/data/postgres/config/BasePostgresDataConfigTest.java @@ -0,0 +1,122 @@ +/* + * Copyright 2020 American Express Travel Related Services Company, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package io.americanexpress.synapse.data.postgres.config; + +import io.americanexpress.synapse.data.postgres.entity.Product; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.PersistenceUnit; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.stat.Statistics; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +/** + * Integration tests for verifying the second-level cache behavior in the Postgres data module. + *

+ * Tests include cache put, hit, and eviction scenarios using the {@link Product} entity. + * The tests are run with the {@link DataSampleConfig} configuration and use Hibernate statistics + * to assert cache operations. + *

+ * + * @author Aziz Ali + */ +@SpringBootTest(classes = {DataSampleConfig.class}) +class BasePostgresDataConfigTest { + + @PersistenceUnit + private EntityManagerFactory emf; + + private Statistics stats; + private Product product1, product2, product3; + + @BeforeEach + void setUp() { + SessionFactoryImplementor sfi = emf.unwrap(SessionFactoryImplementor.class); + stats = sfi.getStatistics(); + stats.clear(); + stats.setStatisticsEnabled(true); + + EntityManager em = emf.createEntityManager(); + em.getTransaction() + .begin(); + product1 = new Product(); + product1.setProductName("Cached Product1"); + product2 = new Product(); + product2.setProductName("Cached Product2"); + product3 = new Product(); + product3.setProductName("Cached Product3"); + em.persist(product1); + em.persist(product2); + em.persist(product3); + em.flush(); + em.getTransaction() + .commit(); + em.close(); + } + + @Test + void testSecondLevelCachePutOnFind() { + stats.clear(); + findAllProducts(); + assertThat(stats.getSecondLevelCachePutCount()) + .as("Expected three puts on first find") + .isEqualTo(3); + } + + @Test + void testSecondLevelCacheHitOnFind() { + // Populate cache + findAllProducts(); + stats.clear(); + // Access again for hits + findAllProducts(); + assertThat(stats.getSecondLevelCacheHitCount()) + .as("Expected three hits from 2LC") + .isEqualTo(3); + assertThat(stats.getSecondLevelCachePutCount()) + .as("No new puts expected on cache hit") + .isZero(); + } + + @Test + void testSecondLevelCacheMissAfterEviction() throws InterruptedException { + // Populate cache + findAllProducts(); + // Wait for TTL eviction (3 seconds as per ehcache.xml) + Thread.sleep(5000); + stats.clear(); + findAllProducts(); + assertThat(stats.getSecondLevelCacheMissCount()) + .as("Expected three misses after TTL eviction") + .isEqualTo(3); + assertThat(stats.getSecondLevelCachePutCount()) + .as("Expected three puts to reload into 2LC after eviction") + .isEqualTo(3); + } + + private void findAllProducts() { + EntityManager em = emf.createEntityManager(); + em.getTransaction() + .begin(); + em.find(Product.class, product1.getId()); + em.find(Product.class, product2.getId()); + em.find(Product.class, product3.getId()); + em.getTransaction() + .commit(); + em.close(); + } +} \ No newline at end of file diff --git a/data/synapse-data-postgres/src/test/java/io/americanexpress/synapse/data/postgres/config/DataSampleConfig.java b/data/synapse-data-postgres/src/test/java/io/americanexpress/synapse/data/postgres/config/DataSampleConfig.java new file mode 100644 index 000000000..c9ff0386f --- /dev/null +++ b/data/synapse-data-postgres/src/test/java/io/americanexpress/synapse/data/postgres/config/DataSampleConfig.java @@ -0,0 +1,48 @@ +/* + * Copyright 2020 American Express Travel Related Services Company, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package io.americanexpress.synapse.data.postgres.config; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; + +/** + * Configuration class for the sample Postgres data module. + *

+ * Loads properties from {@code kocho-application.properties}, enables JPA repositories, + * and configures entity scanning for the {@code io.americanexpress.synapse.data.postgres.entity} package. + *

+ * + * @author Aziz Ali + */ +@Configuration +@PropertySource("classpath:/kocho-application.properties") +@EnableJpaRepositories(basePackages = "io.americanexpress.synapse.data.postgres.entity") +@EnableAutoConfiguration +public class DataSampleConfig extends BasePostgresDataConfig { + + static final String PACKAGE_NAME = "io.americanexpress.synapse.data.postgres"; + + public DataSampleConfig(Environment environment) { + super(environment); + } + + @Override + protected void setPackagesToScan(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) { + entityManagerFactoryBean.setPackagesToScan(PACKAGE_NAME + ENTITY_PACKAGE_NAME); + } +} diff --git a/data/synapse-data-postgres/src/test/java/io/americanexpress/synapse/data/postgres/entity/Product.java b/data/synapse-data-postgres/src/test/java/io/americanexpress/synapse/data/postgres/entity/Product.java new file mode 100644 index 000000000..c0fe0d44e --- /dev/null +++ b/data/synapse-data-postgres/src/test/java/io/americanexpress/synapse/data/postgres/entity/Product.java @@ -0,0 +1,46 @@ +/* + * Copyright 2020 American Express Travel Related Services Company, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package io.americanexpress.synapse.data.postgres.entity; + +import jakarta.persistence.Cacheable; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import org.hibernate.annotations.Cache; +import org.hibernate.annotations.CacheConcurrencyStrategy; + +/** + * Entity representing a product in the database. + *

+ * This class is cacheable and uses Hibernate's second-level cache with read-write concurrency. + * Inherits common entity fields from {@link BaseEntity}. + *

+ * + * @author Aziz Ali + */ +@Entity +@Cacheable +@Cache(usage = CacheConcurrencyStrategy.READ_WRITE) +public class Product extends BaseEntity { + + @Column(name = "product_name") + private String productName; + + public String getProductName() { + return productName; + } + + public void setProductName(String title) { + this.productName = title; + } +} \ No newline at end of file diff --git a/data/synapse-data-postgres/src/test/resources/data.sql b/data/synapse-data-postgres/src/test/resources/data.sql new file mode 100644 index 000000000..019c20ac8 --- /dev/null +++ b/data/synapse-data-postgres/src/test/resources/data.sql @@ -0,0 +1,10 @@ +SET +SCHEMA_SEARCH_PATH TO synapse; +insert into product (id, product_name, created_date_time, last_modified_date_time, created_by, + last_modified_by, version) +values (1, 'Synapse', now(), + now(), 'John-Appleseed@email.com', 'John-Appleseed@email.com', 0); +insert into product (id, product_name, created_date_time, last_modified_date_time, created_by, + last_modified_by, version) +values (2, 'Revenge of Synapse', now(), + now(), 'John-Appleseed@email.com', 'John-Appleseed@email.com', 0); diff --git a/data/synapse-data-postgres/src/test/resources/ehcache.xml b/data/synapse-data-postgres/src/test/resources/ehcache.xml new file mode 100644 index 000000000..11332720a --- /dev/null +++ b/data/synapse-data-postgres/src/test/resources/ehcache.xml @@ -0,0 +1,19 @@ + + + + + + + + + 3 + + 10 + + \ No newline at end of file diff --git a/data/synapse-data-postgres/src/test/resources/kocho-application.properties b/data/synapse-data-postgres/src/test/resources/kocho-application.properties new file mode 100644 index 000000000..5e184d273 --- /dev/null +++ b/data/synapse-data-postgres/src/test/resources/kocho-application.properties @@ -0,0 +1,20 @@ +#Datasource in memory database H2 connection +spring.datasource.jdbcUrl=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1;MODE=LEGACY +spring.datasource.username=sa +spring.datasource.password=sa +spring.datasource.driver-class-name=org.h2.Driver +hibernate.dialect=org.hibernate.dialect.H2Dialect +#H2 default for unit test and local +spring.jpa.properties.hibernate.default_schema=PUBLIC +#Connection pool +spring.datasource.connectionTimeout=15000 +spring.datasource.idleTimeout=300000 +spring.datasource.maxLifetime=900000 +spring.datasource.maximumPoolSize=3 + +spring.datasource.initialization-mode=always + +hibernate.hbm2ddl.auto=none +hibernate.show_sql=true +spring.profiles.active=test +hibernate.format_sql=true \ No newline at end of file diff --git a/data/synapse-data-postgres/src/test/resources/schema.sql b/data/synapse-data-postgres/src/test/resources/schema.sql new file mode 100644 index 000000000..dc9ebe6bc --- /dev/null +++ b/data/synapse-data-postgres/src/test/resources/schema.sql @@ -0,0 +1,23 @@ +DROP SCHEMA IF EXISTS synapse CASCADE; +CREATE SCHEMA synapse; + +SET +SCHEMA_SEARCH_PATH TO synapse; + +DROP TABLE IF EXISTS product CASCADE; + +/* + * product table create script + */ +create table product +( + id serial PRIMARY KEY NOT NULL, + product_name VARCHAR(150) NOT NULL, + created_by VARCHAR(100), + last_modified_by VARCHAR(100), + created_date_time TIMESTAMP DEFAULT current_timestamp, + last_modified_date_time TIMESTAMP, + version INTEGER NOT NULL +); + +COMMIT; diff --git a/pom.xml b/pom.xml index f7e6a849d..166eb1b9b 100644 --- a/pom.xml +++ b/pom.xml @@ -639,11 +639,12 @@ org.ehcache ehcache + 3.10.8 - - org.hibernate + org.hibernate.orm hibernate-jcache + 6.6.17.Final org.hibernate