killbill-memoizeit
Changes
account/pom.xml 5(+5 -0)
beatrix/pom.xml 5(+5 -0)
catalog/pom.xml 5(+5 -0)
currency/pom.xml 5(+5 -0)
entitlement/pom.xml 5(+5 -0)
invoice/pom.xml 5(+5 -0)
jaxrs/pom.xml 5(+5 -0)
junction/pom.xml 5(+5 -0)
overdue/pom.xml 5(+5 -0)
payment/pom.xml 5(+5 -0)
profiles/killbill/pom.xml 5(+5 -0)
profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillBillShiroWebModule.java 15(+14 -1)
subscription/pom.xml 5(+5 -0)
tenant/pom.xml 11(+11 -0)
usage/pom.xml 5(+5 -0)
util/pom.xml 9(+9 -0)
Details
account/pom.xml 5(+5 -0)
diff --git a/account/pom.xml b/account/pom.xml
index 331bc4f..b046788 100644
--- a/account/pom.xml
+++ b/account/pom.xml
@@ -64,6 +64,11 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>it.ozimov</groupId>
+ <artifactId>embedded-redis</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<scope>provided</scope>
beatrix/pom.xml 5(+5 -0)
diff --git a/beatrix/pom.xml b/beatrix/pom.xml
index 4b30973..4385631 100644
--- a/beatrix/pom.xml
+++ b/beatrix/pom.xml
@@ -76,6 +76,11 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>it.ozimov</groupId>
+ <artifactId>embedded-redis</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
</dependency>
catalog/pom.xml 5(+5 -0)
diff --git a/catalog/pom.xml b/catalog/pom.xml
index 05a0edc..6da1d43 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -62,6 +62,11 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>it.ozimov</groupId>
+ <artifactId>embedded-redis</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<scope>provided</scope>
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/TestVersionedCatalog.java b/catalog/src/test/java/org/killbill/billing/catalog/TestVersionedCatalog.java
index 8e4b9c9..964fa3a 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/TestVersionedCatalog.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/TestVersionedCatalog.java
@@ -29,10 +29,16 @@ import org.killbill.billing.catalog.api.CatalogApiException;
import org.killbill.billing.catalog.api.Currency;
import org.killbill.billing.catalog.api.Plan;
import org.killbill.billing.catalog.api.PlanSpecifier;
+import org.killbill.billing.catalog.api.Product;
+import org.killbill.billing.catalog.rules.DefaultPlanRules;
+import org.redisson.client.codec.Codec;
+import org.redisson.codec.SerializationCodec;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
+import io.netty.buffer.ByteBuf;
+
public class TestVersionedCatalog extends CatalogTestSuiteNoDB {
final DateTime dt0 = new DateTime("2010-01-01T00:00:00+00:00");
@@ -168,4 +174,38 @@ public class TestVersionedCatalog extends CatalogTestSuiteNoDB {
// This would be called for instance when computing billing events (dt3 could be a future PHASE event for instance)
vc.findPlan("shotgun-quarterly", dt3, dt1);
}
+
+ @Test(groups = "fast")
+ public void testDefaultPlanRulesExternalizable() throws IOException {
+ final Codec codec = new SerializationCodec();
+ final ByteBuf byteBuf = codec.getValueEncoder().encode(vc.getVersions().get(0).getPlanRules());
+ final DefaultPlanRules planRules = (DefaultPlanRules) codec.getValueDecoder().decode(byteBuf, null);
+ Assert.assertEquals(planRules, vc.getVersions().get(0).getPlanRules());
+ }
+
+ @Test(groups = "fast")
+ public void testProductExternalizable() throws IOException {
+ final Codec codec = new SerializationCodec();
+ for (final Product product : vc.getVersions().get(0).getCatalogEntityCollectionProduct().getEntries()) {
+ final ByteBuf byteBuf = codec.getValueEncoder().encode(product);
+ final Product product2 = (Product) codec.getValueDecoder().decode(byteBuf, null);
+ Assert.assertEquals(product2, product);
+ }
+ }
+
+ @Test(groups = "fast")
+ public void testCatalogEntityCollectionProductExternalizable() throws IOException {
+ final Codec codec = new SerializationCodec();
+ final ByteBuf byteBuf = codec.getValueEncoder().encode(vc.getVersions().get(0).getCatalogEntityCollectionProduct());
+ final Collection products = (CatalogEntityCollection) codec.getValueDecoder().decode(byteBuf, null);
+ Assert.assertEquals(products, vc.getVersions().get(0).getCatalogEntityCollectionProduct());
+ }
+
+ @Test(groups = "fast")
+ public void testStandaloneCatalogExternalizable() throws IOException {
+ final Codec codec = new SerializationCodec();
+ final ByteBuf byteBuf = codec.getValueEncoder().encode(vc.getVersions().get(0));
+ final StandaloneCatalog standaloneCatalog = (StandaloneCatalog) codec.getValueDecoder().decode(byteBuf, null);
+ Assert.assertEquals(standaloneCatalog, vc.getVersions().get(0));
+ }
}
currency/pom.xml 5(+5 -0)
diff --git a/currency/pom.xml b/currency/pom.xml
index 61de314..23a2846 100644
--- a/currency/pom.xml
+++ b/currency/pom.xml
@@ -47,6 +47,11 @@
<scope>provided</scope>
</dependency>
<dependency>
+ <groupId>it.ozimov</groupId>
+ <artifactId>embedded-redis</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<scope>provided</scope>
entitlement/pom.xml 5(+5 -0)
diff --git a/entitlement/pom.xml b/entitlement/pom.xml
index 7e68eca..11e9e78 100644
--- a/entitlement/pom.xml
+++ b/entitlement/pom.xml
@@ -60,6 +60,11 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>it.ozimov</groupId>
+ <artifactId>embedded-redis</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<scope>provided</scope>
invoice/pom.xml 5(+5 -0)
diff --git a/invoice/pom.xml b/invoice/pom.xml
index 9becc1d..810f9fa 100644
--- a/invoice/pom.xml
+++ b/invoice/pom.xml
@@ -65,6 +65,11 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>it.ozimov</groupId>
+ <artifactId>embedded-redis</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<scope>provided</scope>
jaxrs/pom.xml 5(+5 -0)
diff --git a/jaxrs/pom.xml b/jaxrs/pom.xml
index 4ba84f6..4239397 100644
--- a/jaxrs/pom.xml
+++ b/jaxrs/pom.xml
@@ -71,6 +71,11 @@
<artifactId>swagger-models</artifactId>
</dependency>
<dependency>
+ <groupId>it.ozimov</groupId>
+ <artifactId>embedded-redis</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<scope>provided</scope>
junction/pom.xml 5(+5 -0)
diff --git a/junction/pom.xml b/junction/pom.xml
index 64d65b0..5b341c0 100644
--- a/junction/pom.xml
+++ b/junction/pom.xml
@@ -60,6 +60,11 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>it.ozimov</groupId>
+ <artifactId>embedded-redis</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
overdue/pom.xml 5(+5 -0)
diff --git a/overdue/pom.xml b/overdue/pom.xml
index b13bd40..453613f 100644
--- a/overdue/pom.xml
+++ b/overdue/pom.xml
@@ -64,6 +64,11 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>it.ozimov</groupId>
+ <artifactId>embedded-redis</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<scope>provided</scope>
payment/pom.xml 5(+5 -0)
diff --git a/payment/pom.xml b/payment/pom.xml
index 1926973..3013ed7 100644
--- a/payment/pom.xml
+++ b/payment/pom.xml
@@ -79,6 +79,11 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>it.ozimov</groupId>
+ <artifactId>embedded-redis</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
</dependency>
profiles/killbill/pom.xml 5(+5 -0)
diff --git a/profiles/killbill/pom.xml b/profiles/killbill/pom.xml
index 44e9514..e2dce78 100644
--- a/profiles/killbill/pom.xml
+++ b/profiles/killbill/pom.xml
@@ -130,6 +130,11 @@
<artifactId>swagger-jersey-jaxrs</artifactId>
</dependency>
<dependency>
+ <groupId>it.ozimov</groupId>
+ <artifactId>embedded-redis</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
</dependency>
diff --git a/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillBillShiroWebModule.java b/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillBillShiroWebModule.java
index 5c9437f..90b2144 100644
--- a/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillBillShiroWebModule.java
+++ b/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillBillShiroWebModule.java
@@ -43,9 +43,11 @@ import org.killbill.billing.jaxrs.resources.JaxrsResource;
import org.killbill.billing.server.security.FirstSuccessfulStrategyWith540;
import org.killbill.billing.server.security.KillbillJdbcTenantRealm;
import org.killbill.billing.util.config.definition.RbacConfig;
+import org.killbill.billing.util.config.definition.RedisCacheConfig;
import org.killbill.billing.util.glue.EhcacheShiroManagerProvider;
import org.killbill.billing.util.glue.KillBillShiroModule;
import org.killbill.billing.util.glue.RealmsFromShiroIniProvider;
+import org.killbill.billing.util.glue.RedisShiroManagerProvider;
import org.killbill.billing.util.glue.SessionDAOProvider;
import org.killbill.billing.util.security.shiro.realm.KillBillJdbcRealm;
import org.killbill.billing.util.security.shiro.realm.KillBillJndiLdapRealm;
@@ -75,8 +77,19 @@ public class KillBillShiroWebModule extends ShiroWebModuleWith435 {
@Override
protected void configureShiroWeb() {
+ final RedisCacheConfig redisCacheConfig = new ConfigurationObjectFactory(new ConfigSource() {
+ @Override
+ public String getString(final String propertyName) {
+ return configSource.getString(propertyName);
+ }
+ }).build(RedisCacheConfig.class);
+
// Magic provider to configure the cache manager
- bind(CacheManager.class).toProvider(EhcacheShiroManagerProvider.class).asEagerSingleton();
+ if (redisCacheConfig.isRedisCachingEnabled()) {
+ bind(CacheManager.class).toProvider(RedisShiroManagerProvider.class).asEagerSingleton();
+ } else {
+ bind(CacheManager.class).toProvider(EhcacheShiroManagerProvider.class).asEagerSingleton();
+ }
configureShiroForRBAC();
subscription/pom.xml 5(+5 -0)
diff --git a/subscription/pom.xml b/subscription/pom.xml
index 774613d..2c6008b 100644
--- a/subscription/pom.xml
+++ b/subscription/pom.xml
@@ -60,6 +60,11 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>it.ozimov</groupId>
+ <artifactId>embedded-redis</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<scope>provided</scope>
tenant/pom.xml 11(+11 -0)
diff --git a/tenant/pom.xml b/tenant/pom.xml
index 9c43791..48bf333 100644
--- a/tenant/pom.xml
+++ b/tenant/pom.xml
@@ -60,6 +60,11 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>it.ozimov</groupId>
+ <artifactId>embedded-redis</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
</dependency>
@@ -149,6 +154,12 @@
<artifactId>killbill-queue</artifactId>
</dependency>
<dependency>
+ <groupId>org.kill-bill.commons</groupId>
+ <artifactId>killbill-queue</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<scope>test</scope>
diff --git a/tenant/src/main/java/org/killbill/billing/tenant/api/TenantCacheInvalidation.java b/tenant/src/main/java/org/killbill/billing/tenant/api/TenantCacheInvalidation.java
index cc48190..9f2ee18 100644
--- a/tenant/src/main/java/org/killbill/billing/tenant/api/TenantCacheInvalidation.java
+++ b/tenant/src/main/java/org/killbill/billing/tenant/api/TenantCacheInvalidation.java
@@ -179,6 +179,7 @@ public class TenantCacheInvalidation {
final Collection<CacheInvalidationCallback> callbacks = parent.getCacheInvalidations(tenantKeyAndCookie.getTenantKey());
if (!callbacks.isEmpty()) {
final InternalTenantContext tenantContext = new InternalTenantContext(cur.getTenantRecordId());
+ // TODO In case of Redis, we don't want any invalidation, but we still want the events to notify the plugins (ideally, our bus would also support a Topic model)
for (final CacheInvalidationCallback callback : callbacks) {
callback.invalidateCache(tenantKeyAndCookie.getTenantKey(), tenantKeyAndCookie.getCookie(), tenantContext);
}
diff --git a/tenant/src/test/java/org/killbill/billing/tenant/api/TestDefaultTenant.java b/tenant/src/test/java/org/killbill/billing/tenant/api/TestDefaultTenant.java
new file mode 100644
index 0000000..29a20c7
--- /dev/null
+++ b/tenant/src/test/java/org/killbill/billing/tenant/api/TestDefaultTenant.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you 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 org.killbill.billing.tenant.api;
+
+import java.io.IOException;
+import java.util.UUID;
+
+import org.killbill.billing.tenant.TenantTestSuiteNoDB;
+import org.redisson.client.codec.Codec;
+import org.redisson.codec.SerializationCodec;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import io.netty.buffer.ByteBuf;
+
+public class TestDefaultTenant extends TenantTestSuiteNoDB {
+
+ @Test(groups = "fast")
+ public void testExternalizable() throws IOException {
+ final DefaultTenant tenantdata = new DefaultTenant(UUID.randomUUID(), clock.getUTCNow(), clock.getUTCNow(), "er44TT-yy4r", "TTR445ee2", null);
+ final Codec code = new SerializationCodec();
+ final ByteBuf byteBuf = code.getValueEncoder().encode(tenantdata);
+ final DefaultTenant tenantData2 = (DefaultTenant) code.getValueDecoder().decode(byteBuf, null);
+ Assert.assertEquals(tenantData2, tenantdata);
+ }
+}
\ No newline at end of file
usage/pom.xml 5(+5 -0)
diff --git a/usage/pom.xml b/usage/pom.xml
index bf1ace3..94ab0dd 100644
--- a/usage/pom.xml
+++ b/usage/pom.xml
@@ -55,6 +55,11 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>it.ozimov</groupId>
+ <artifactId>embedded-redis</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<scope>provided</scope>
util/pom.xml 9(+9 -0)
diff --git a/util/pom.xml b/util/pom.xml
index 7ea6171..5c7126e 100644
--- a/util/pom.xml
+++ b/util/pom.xml
@@ -115,6 +115,11 @@
<artifactId>metrics-jcache</artifactId>
</dependency>
<dependency>
+ <groupId>it.ozimov</groupId>
+ <artifactId>embedded-redis</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
</dependency>
@@ -284,6 +289,10 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>org.redisson</groupId>
+ <artifactId>redisson</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.skife.config</groupId>
<artifactId>config-magic</artifactId>
</dependency>
diff --git a/util/src/main/java/org/killbill/billing/util/config/definition/RedisCacheConfig.java b/util/src/main/java/org/killbill/billing/util/config/definition/RedisCacheConfig.java
new file mode 100644
index 0000000..cbe8f34
--- /dev/null
+++ b/util/src/main/java/org/killbill/billing/util/config/definition/RedisCacheConfig.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you 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 org.killbill.billing.util.config.definition;
+
+import org.skife.config.Config;
+import org.skife.config.Default;
+import org.skife.config.Description;
+
+public interface RedisCacheConfig extends KillbillConfig {
+
+ @Config("org.killbill.cache.config.redis")
+ @Default("false")
+ @Description("Whether Redis integration for caching is enabled")
+ public boolean isRedisCachingEnabled();
+
+ @Config("org.killbill.cache.config.redis.url")
+ @Default("redis://127.0.0.1:6379")
+ @Description("Redis URL")
+ public String getUrl();
+
+ @Config("org.killbill.cache.config.redis.connectionMinimumIdleSize")
+ @Default("1")
+ @Description("Minimum number of connections")
+ public int getConnectionMinimumIdleSize();
+}
diff --git a/util/src/main/java/org/killbill/billing/util/glue/CacheModule.java b/util/src/main/java/org/killbill/billing/util/glue/CacheModule.java
index 40b55b5..8289c70 100644
--- a/util/src/main/java/org/killbill/billing/util/glue/CacheModule.java
+++ b/util/src/main/java/org/killbill/billing/util/glue/CacheModule.java
@@ -42,6 +42,8 @@ import org.killbill.billing.util.cache.TenantOverdueConfigCacheLoader;
import org.killbill.billing.util.cache.TenantRecordIdCacheLoader;
import org.killbill.billing.util.cache.TenantStateMachineConfigCacheLoader;
import org.killbill.billing.util.config.definition.EhCacheConfig;
+import org.killbill.billing.util.config.definition.RedisCacheConfig;
+import org.redisson.api.RedissonClient;
import org.skife.config.ConfigurationObjectFactory;
import com.google.inject.multibindings.Multibinder;
@@ -50,6 +52,8 @@ import com.google.inject.util.Providers;
public class CacheModule extends KillBillModule {
+ public static final String REDIS_CACHE_CLIENT = "redisCacheClient";
+
public CacheModule(final KillbillConfigSource configSource) {
super(configSource);
}
@@ -59,8 +63,16 @@ public class CacheModule extends KillBillModule {
final EhCacheConfig ehCacheConfig = new ConfigurationObjectFactory(skifeConfigSource).build(EhCacheConfig.class);
bind(EhCacheConfig.class).toInstance(ehCacheConfig);
- // EhCache specifics
- bind(CacheManager.class).toProvider(Eh107CacheManagerProvider.class).asEagerSingleton();
+ final RedisCacheConfig redisCacheConfig = new ConfigurationObjectFactory(skifeConfigSource).build(RedisCacheConfig.class);
+ bind(RedisCacheConfig.class).toInstance(redisCacheConfig);
+
+ if (redisCacheConfig.isRedisCachingEnabled()) {
+ bind(RedissonClient.class).annotatedWith(Names.named(REDIS_CACHE_CLIENT)).toProvider(RedissonCacheClientProvider.class).asEagerSingleton();
+ bind(CacheManager.class).toProvider(Redis107CacheManagerProvider.class).asEagerSingleton();
+ } else {
+ bind(RedissonClient.class).annotatedWith(Names.named(REDIS_CACHE_CLIENT)).toProvider(Providers.<RedissonClient>of(null));
+ bind(CacheManager.class).toProvider(Eh107CacheManagerProvider.class).asEagerSingleton();
+ }
// Kill Bill generic cache dispatcher
bind(CacheControllerDispatcher.class).toProvider(CacheControllerDispatcherProvider.class).asEagerSingleton();
diff --git a/util/src/main/java/org/killbill/billing/util/glue/KillBillShiroModule.java b/util/src/main/java/org/killbill/billing/util/glue/KillBillShiroModule.java
index 07a9613..420a565 100644
--- a/util/src/main/java/org/killbill/billing/util/glue/KillBillShiroModule.java
+++ b/util/src/main/java/org/killbill/billing/util/glue/KillBillShiroModule.java
@@ -27,6 +27,7 @@ import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.killbill.billing.platform.api.KillbillConfigSource;
import org.killbill.billing.util.config.definition.RbacConfig;
+import org.killbill.billing.util.config.definition.RedisCacheConfig;
import org.killbill.billing.util.security.shiro.realm.KillBillJdbcRealm;
import org.killbill.billing.util.security.shiro.realm.KillBillJndiLdapRealm;
import org.killbill.billing.util.security.shiro.realm.KillBillOktaRealm;
@@ -112,8 +113,19 @@ public class KillBillShiroModule extends ShiroModule {
protected void bindSecurityManager(final AnnotatedBindingBuilder<? super SecurityManager> bind) {
super.bindSecurityManager(bind);
+ final RedisCacheConfig redisCacheConfig = new ConfigurationObjectFactory(new ConfigSource() {
+ @Override
+ public String getString(final String propertyName) {
+ return configSource.getString(propertyName);
+ }
+ }).build(RedisCacheConfig.class);
+
// Magic provider to configure the cache manager
- bind(CacheManager.class).toProvider(EhcacheShiroManagerProvider.class).asEagerSingleton();
+ if (redisCacheConfig.isRedisCachingEnabled()) {
+ bind(CacheManager.class).toProvider(RedisShiroManagerProvider.class).asEagerSingleton();
+ } else {
+ bind(CacheManager.class).toProvider(EhcacheShiroManagerProvider.class).asEagerSingleton();
+ }
}
@Override
diff --git a/util/src/main/java/org/killbill/billing/util/glue/Redis107CacheManagerProvider.java b/util/src/main/java/org/killbill/billing/util/glue/Redis107CacheManagerProvider.java
new file mode 100644
index 0000000..1d51e13
--- /dev/null
+++ b/util/src/main/java/org/killbill/billing/util/glue/Redis107CacheManagerProvider.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you 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 org.killbill.billing.util.glue;
+
+import java.util.Set;
+
+import javax.cache.CacheManager;
+import javax.cache.Caching;
+import javax.cache.spi.CachingProvider;
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.killbill.billing.util.cache.BaseCacheLoader;
+import org.redisson.api.RedissonClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.codahale.metrics.MetricRegistry;
+import com.google.inject.name.Named;
+
+import static org.killbill.billing.util.glue.CacheModule.REDIS_CACHE_CLIENT;
+
+public class Redis107CacheManagerProvider extends RedisCacheProviderBase implements Provider<CacheManager> {
+
+ private static final Logger logger = LoggerFactory.getLogger(Redis107CacheManagerProvider.class);
+
+ private final Set<BaseCacheLoader> cacheLoaders;
+
+ @Inject
+ public Redis107CacheManagerProvider(final MetricRegistry metricRegistry,
+ @Named(REDIS_CACHE_CLIENT) final RedissonClient redissonClient,
+ final Set<BaseCacheLoader> cacheLoaders) {
+ super(metricRegistry, redissonClient);
+ this.cacheLoaders = cacheLoaders;
+ }
+
+ @Override
+ public CacheManager get() {
+ // JSR-107 registration, required for JMX integration
+ final CachingProvider cachingProvider = Caching.getCachingProvider("org.redisson.jcache.JCachingProvider");
+
+ final CacheManager cacheManager = cachingProvider.getCacheManager();
+
+ for (final BaseCacheLoader<?, ?> cacheLoader : cacheLoaders) {
+ createCache(cacheManager,
+ cacheLoader.getCacheType().getCacheName(),
+ cacheLoader.getCacheType().getKeyType(),
+ cacheLoader.getCacheType().getValueType());
+ }
+
+ return cacheManager;
+ }
+}
diff --git a/util/src/main/java/org/killbill/billing/util/glue/RedisCacheProviderBase.java b/util/src/main/java/org/killbill/billing/util/glue/RedisCacheProviderBase.java
new file mode 100644
index 0000000..1a5effc
--- /dev/null
+++ b/util/src/main/java/org/killbill/billing/util/glue/RedisCacheProviderBase.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you 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 org.killbill.billing.util.glue;
+
+import javax.cache.CacheManager;
+import javax.cache.configuration.Configuration;
+import javax.cache.configuration.MutableConfiguration;
+
+import org.redisson.api.RedissonClient;
+import org.redisson.jcache.configuration.RedissonConfiguration;
+
+import com.codahale.metrics.MetricRegistry;
+
+abstract class RedisCacheProviderBase extends CacheProviderBase {
+
+ private final RedissonClient redissonClient;
+
+ RedisCacheProviderBase(final MetricRegistry metricRegistry, final RedissonClient redissonClient) {
+ super(metricRegistry);
+ this.redissonClient = redissonClient;
+ }
+
+ <K, V> void createCache(final CacheManager cacheManager, final String cacheName, final Class<K> keyType, final Class<V> valueType) {
+ final Configuration jcacheConfig = new MutableConfiguration().setTypes(keyType, valueType);
+
+ final Configuration redissonConfiguration = RedissonConfiguration.fromInstance(redissonClient, jcacheConfig);
+
+ createCache(cacheManager, cacheName, redissonConfiguration);
+ }
+}
diff --git a/util/src/main/java/org/killbill/billing/util/glue/RedisShiroManager.java b/util/src/main/java/org/killbill/billing/util/glue/RedisShiroManager.java
new file mode 100644
index 0000000..0a08407
--- /dev/null
+++ b/util/src/main/java/org/killbill/billing/util/glue/RedisShiroManager.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you 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 org.killbill.billing.util.glue;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Set;
+
+import javax.cache.Cache.Entry;
+
+import org.apache.shiro.cache.Cache;
+import org.apache.shiro.cache.CacheException;
+import org.apache.shiro.cache.CacheManager;
+import org.redisson.api.RedissonClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.codahale.metrics.MetricRegistry;
+
+public class RedisShiroManager extends RedisCacheProviderBase implements CacheManager {
+
+ private static final Logger log = LoggerFactory.getLogger(RedisShiroManager.class);
+
+ private final javax.cache.CacheManager eh107CacheManager;
+
+ public RedisShiroManager(final javax.cache.CacheManager eh107CacheManager,
+ final MetricRegistry metricRegistry,
+ final RedissonClient redissonClient) {
+ super(metricRegistry, redissonClient);
+ this.eh107CacheManager = eh107CacheManager;
+ }
+
+ @Override
+ public <K, V> Cache<K, V> getCache(final String name) throws CacheException {
+ log.trace("Acquiring RedisShiro instance named [{}]", name);
+
+ javax.cache.Cache<Object, Object> cache = eh107CacheManager.getCache(name, Object.class, Object.class);
+
+ if (cache == null) {
+ log.info("Cache with name {} does not yet exist. Creating now.", name);
+ createCache(eh107CacheManager, name, Object.class, Object.class);
+ cache = eh107CacheManager.getCache(name, Object.class, Object.class);
+ log.info("Added RedisShiro named [{}]", name);
+ } else {
+ log.info("Using existing RedisShiro named [{}]", name);
+ }
+
+ return new RedisCache<K, V>(cache);
+ }
+
+ private static final class RedisCache<K, V> implements Cache<K, V> {
+
+ private final javax.cache.Cache<K, V> cache;
+
+ public RedisCache(final javax.cache.Cache cache) {
+ this.cache = cache;
+
+ }
+
+ @Override
+ public V get(final K key) throws CacheException {
+ return cache.get(key);
+ }
+
+ @Override
+ public V put(final K key, final V value) throws CacheException {
+ V previousValue;
+ while (true) {
+ previousValue = cache.get(key);
+ if (previousValue == null) {
+ if (cache.putIfAbsent(key, value)) {
+ break;
+ }
+ } else {
+ if (cache.replace(key, value)) {
+ break;
+ }
+ }
+ }
+
+ return previousValue;
+ }
+
+ @Override
+ public V remove(final K key) throws CacheException {
+ V previousValue;
+ while (true) {
+ previousValue = cache.get(key);
+ if (previousValue == null) {
+ break;
+ } else {
+ if (cache.remove(key)) {
+ break;
+ }
+ }
+ }
+
+ return previousValue;
+ }
+
+ @Override
+ public void clear() throws CacheException {
+ cache.clear();
+ }
+
+ @Override
+ public int size() {
+ return keys().size();
+ }
+
+ @Override
+ public Set<K> keys() {
+ final Set<K> result = new HashSet<K>();
+ for (final Entry<K, V> entry : cache) {
+ result.add(entry.getKey());
+ }
+ return result;
+ }
+
+ @Override
+ public Collection<V> values() {
+ final Collection<V> result = new LinkedList<V>();
+ for (final Entry<K, V> entry : cache) {
+ result.add(entry.getValue());
+ }
+ return result;
+ }
+ }
+}
diff --git a/util/src/main/java/org/killbill/billing/util/glue/RedisShiroManagerProvider.java b/util/src/main/java/org/killbill/billing/util/glue/RedisShiroManagerProvider.java
new file mode 100644
index 0000000..bcfa133
--- /dev/null
+++ b/util/src/main/java/org/killbill/billing/util/glue/RedisShiroManagerProvider.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you 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 org.killbill.billing.util.glue;
+
+import javax.cache.CacheManager;
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.apache.shiro.mgt.DefaultSecurityManager;
+import org.apache.shiro.mgt.SecurityManager;
+import org.redisson.api.RedissonClient;
+
+import com.codahale.metrics.MetricRegistry;
+import com.google.inject.name.Named;
+
+import static org.killbill.billing.util.glue.CacheModule.REDIS_CACHE_CLIENT;
+
+public class RedisShiroManagerProvider implements Provider<RedisShiroManager> {
+
+ private final CacheManager eh107CacheManager;
+ private final SecurityManager securityManager;
+ private final MetricRegistry metricRegistry;
+ private final RedissonClient redissonClient;
+
+ @Inject
+ public RedisShiroManagerProvider(final SecurityManager securityManager,
+ final CacheManager eh107CacheManager,
+ final MetricRegistry metricRegistry,
+ @Named(REDIS_CACHE_CLIENT) final RedissonClient redissonClient) {
+ this.securityManager = securityManager;
+ this.eh107CacheManager = eh107CacheManager;
+ this.metricRegistry = metricRegistry;
+ this.redissonClient = redissonClient;
+ }
+
+ @Override
+ public RedisShiroManager get() {
+ // Same Redis manager instance as the rest of the system
+ final RedisShiroManager shiroRedisManager = new RedisShiroManager(eh107CacheManager, metricRegistry, redissonClient);
+
+ if (securityManager instanceof DefaultSecurityManager) {
+ // For RBAC only (see also KillbillJdbcTenantRealmProvider)
+ final DefaultSecurityManager securityManager = (DefaultSecurityManager) this.securityManager;
+ securityManager.setCacheManager(shiroRedisManager);
+ securityManager.setSubjectDAO(new KillBillSubjectDAO());
+ }
+
+ return shiroRedisManager;
+ }
+}
diff --git a/util/src/main/java/org/killbill/billing/util/glue/RedissonCacheClientProvider.java b/util/src/main/java/org/killbill/billing/util/glue/RedissonCacheClientProvider.java
new file mode 100644
index 0000000..8d4f958
--- /dev/null
+++ b/util/src/main/java/org/killbill/billing/util/glue/RedissonCacheClientProvider.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you 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 org.killbill.billing.util.glue;
+
+import javax.inject.Inject;
+
+import org.killbill.billing.util.config.definition.RedisCacheConfig;
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.client.codec.Codec;
+import org.redisson.codec.SerializationCodec;
+import org.redisson.config.Config;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.inject.Provider;
+
+public class RedissonCacheClientProvider implements Provider<RedissonClient> {
+
+ private final String address;
+ private final int connectionMinimumIdleSize;
+
+ @Inject
+ public RedissonCacheClientProvider(final RedisCacheConfig cacheConfig) {
+ this(cacheConfig.getUrl(), cacheConfig.getConnectionMinimumIdleSize());
+ }
+
+ @VisibleForTesting
+ public RedissonCacheClientProvider(final String address, final int connectionMinimumIdleSize) {
+ this.address = address;
+ this.connectionMinimumIdleSize = connectionMinimumIdleSize;
+ }
+
+ @Override
+ public RedissonClient get() {
+ // JDK serialization codec for now, but we can do better in speed and space
+ final Codec codec = new SerializationCodec();
+
+ final Config redissonCfg = new Config();
+ redissonCfg.setCodec(codec)
+ .useSingleServer()
+ .setAddress(address)
+ .setConnectionMinimumIdleSize(connectionMinimumIdleSize);
+ return Redisson.create(redissonCfg);
+ }
+}
diff --git a/util/src/main/java/org/killbill/billing/util/glue/SessionDAOProvider.java b/util/src/main/java/org/killbill/billing/util/glue/SessionDAOProvider.java
index a771c9c..0cfba7e 100644
--- a/util/src/main/java/org/killbill/billing/util/glue/SessionDAOProvider.java
+++ b/util/src/main/java/org/killbill/billing/util/glue/SessionDAOProvider.java
@@ -27,7 +27,9 @@ import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.CachingSessionDAO;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.killbill.billing.util.config.definition.RbacConfig;
+import org.killbill.billing.util.config.definition.RedisCacheConfig;
import org.killbill.billing.util.security.shiro.dao.JDBCSessionDao;
+import org.killbill.billing.util.security.shiro.dao.RedisSessionDao;
import org.skife.jdbi.v2.IDBI;
import static org.killbill.billing.util.glue.IDBISetup.MAIN_RO_IDBI_NAMED;
@@ -38,18 +40,25 @@ public class SessionDAOProvider implements Provider<SessionDAO> {
private final IDBI dbi;
private final IDBI roDbi;
private final RbacConfig rbacConfig;
+ private final RedisCacheConfig redisCacheConfig;
@Inject
- public SessionDAOProvider(final IDBI dbi, @Named(MAIN_RO_IDBI_NAMED) final IDBI roDbi, final SessionManager sessionManager, final RbacConfig rbacConfig) {
+ public SessionDAOProvider(final IDBI dbi, @Named(MAIN_RO_IDBI_NAMED) final IDBI roDbi, final SessionManager sessionManager, final RbacConfig rbacConfig, final RedisCacheConfig redisCacheConfig) {
this.sessionManager = sessionManager;
this.dbi = dbi;
this.roDbi = roDbi;
this.rbacConfig = rbacConfig;
+ this.redisCacheConfig = redisCacheConfig;
}
@Override
public SessionDAO get() {
- final CachingSessionDAO sessionDao = new JDBCSessionDao(dbi, roDbi);
+ final CachingSessionDAO sessionDao;
+ if (redisCacheConfig.isRedisCachingEnabled()) {
+ sessionDao = new RedisSessionDao();
+ } else {
+ sessionDao = new JDBCSessionDao(dbi, roDbi);
+ }
if (sessionManager instanceof DefaultSessionManager) {
final DefaultSessionManager defaultSessionManager = (DefaultSessionManager) sessionManager;
diff --git a/util/src/main/java/org/killbill/billing/util/jackson/ObjectMapper.java b/util/src/main/java/org/killbill/billing/util/jackson/ObjectMapper.java
index 24dbea6..c181efc 100644
--- a/util/src/main/java/org/killbill/billing/util/jackson/ObjectMapper.java
+++ b/util/src/main/java/org/killbill/billing/util/jackson/ObjectMapper.java
@@ -25,7 +25,7 @@ import com.fasterxml.jackson.datatype.joda.JodaModule;
public class ObjectMapper extends com.fasterxml.jackson.databind.ObjectMapper {
- public ObjectMapper(final SmileFactory f) {
+ private ObjectMapper(final SmileFactory f) {
super(f);
this.registerModule(new JodaModule());
this.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
@@ -35,4 +35,9 @@ public class ObjectMapper extends com.fasterxml.jackson.databind.ObjectMapper {
public ObjectMapper() {
this(null);
}
+
+ @Override
+ public com.fasterxml.jackson.databind.ObjectMapper copy() {
+ return new ObjectMapper();
+ }
}
diff --git a/util/src/main/java/org/killbill/billing/util/security/shiro/dao/RedisSessionDao.java b/util/src/main/java/org/killbill/billing/util/security/shiro/dao/RedisSessionDao.java
new file mode 100644
index 0000000..4d356d4
--- /dev/null
+++ b/util/src/main/java/org/killbill/billing/util/security/shiro/dao/RedisSessionDao.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you 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 org.killbill.billing.util.security.shiro.dao;
+
+import java.io.Serializable;
+import java.util.UUID;
+
+import org.apache.shiro.session.Session;
+import org.apache.shiro.session.mgt.eis.CachingSessionDAO;
+import org.killbill.billing.util.UUIDs;
+
+public class RedisSessionDao extends CachingSessionDAO {
+
+ @Override
+ protected Serializable doCreate(final Session session) {
+ final UUID sessionId = UUIDs.randomUUID();
+ // See SessionModelDao#toSimpleSession for why we use toString()
+ final String sessionIdAsString = sessionId.toString();
+ assignSessionId(session, sessionIdAsString);
+ // Make sure to return a String here as well, or Shiro will cache the Session with a UUID key
+ // while it is expecting String
+ return sessionIdAsString;
+ }
+
+ protected Session doReadSession(final Serializable sessionId) {
+ // Should never be executed
+ throw new IllegalStateException("Session should be in Redis");
+ }
+
+ protected void doUpdate(final Session session) {
+ // Does nothing - parent class persists to cache.
+ }
+
+ @Override
+ protected void doDelete(final Session session) {
+ // Does nothing - parent class removes from cache.
+ }
+}
diff --git a/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuite.java b/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuite.java
index 68b9717..1f505ab 100644
--- a/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuite.java
+++ b/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuite.java
@@ -34,11 +34,14 @@ import org.killbill.billing.callcontext.MutableInternalCallContext;
import org.killbill.billing.platform.api.KillbillConfigSource;
import org.killbill.billing.platform.test.config.TestKillbillConfigSource;
import org.killbill.billing.util.callcontext.InternalCallContextFactory;
+import org.killbill.billing.util.glue.RedissonCacheClientProvider;
import org.killbill.clock.Clock;
import org.killbill.clock.ClockMock;
+import org.killbill.clock.DistributedClockMock;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import org.redisson.api.RedissonClient;
import org.skife.config.ConfigSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -55,6 +58,7 @@ import org.testng.annotations.Listeners;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
+import redis.embedded.RedisServer;
import static org.testng.ITestResult.CREATED;
import static org.testng.ITestResult.FAILURE;
@@ -79,6 +83,8 @@ public class GuicyKillbillTestSuite implements IHookable {
protected KillbillConfigSource configSource;
protected ConfigSource skifeConfigSource;
+ private RedissonClient redissonClient;
+
@Inject
protected InternalCallContextFactory internalCallContextFactory;
@@ -88,6 +94,7 @@ public class GuicyKillbillTestSuite implements IHookable {
@Inject
protected MutableCallContext callContext;
+ private RedisServer redisServer;
private boolean hasFailed = false;
@@ -212,9 +219,25 @@ public class GuicyKillbillTestSuite implements IHookable {
@BeforeSuite(alwaysRun = true)
public void globalBeforeSuite() {
- theRealClock.resetDeltaFromReality();
+ if (Boolean.valueOf(System.getProperty("killbill.test.redis", "false"))) {
+ redisServer = new RedisServer(56379);
+ redisServer.start();
+
+ redissonClient = new RedissonCacheClientProvider("redis://127.0.0.1:56379", 1).get();
+
+ theRealClock = new DistributedClockMock();
+ ((DistributedClockMock) theRealClock).setRedissonClient(redissonClient);
+
+ extraPropertiesForTestSuite = ImmutableMap.<String, String>of("org.killbill.cache.config.redis", "true",
+ "org.killbill.cache.config.redis.url", "redis://127.0.0.1:56379");
+ } else {
+ theRealClock.resetDeltaFromReality();
- extraPropertiesForTestSuite = ImmutableMap.<String, String>of();
+ extraPropertiesForTestSuite = ImmutableMap.<String, String>of();
+ }
+
+ // The clock needs to be setup early in @BeforeSuite, as it is needed when starting the server, but see below
+ clock = theRealClock;
}
@BeforeClass(alwaysRun = true)
@@ -250,6 +273,12 @@ public class GuicyKillbillTestSuite implements IHookable {
@AfterSuite(alwaysRun = true)
public void globalAfterSuite() {
+ if (redissonClient != null) {
+ redissonClient.shutdown();
+ }
+ if (redisServer != null) {
+ redisServer.stop();
+ }
}
public boolean hasFailed() {
diff --git a/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuiteWithEmbeddedDB.java b/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuiteWithEmbeddedDB.java
index c282bd2..72bc9a4 100644
--- a/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuiteWithEmbeddedDB.java
+++ b/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuiteWithEmbeddedDB.java
@@ -39,6 +39,7 @@ import javax.sql.DataSource;
import org.killbill.billing.util.cache.CacheControllerDispatcher;
import org.killbill.commons.embeddeddb.EmbeddedDB;
+import org.redisson.api.RedissonClient;
import org.skife.jdbi.v2.IDBI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -50,6 +51,7 @@ import org.testng.annotations.BeforeSuite;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Inject;
+import static org.killbill.billing.util.glue.CacheModule.REDIS_CACHE_CLIENT;
import static org.killbill.billing.util.glue.IDBISetup.MAIN_RO_IDBI_NAMED;
public class GuicyKillbillTestSuiteWithEmbeddedDB extends GuicyKillbillTestSuite {
@@ -76,6 +78,11 @@ public class GuicyKillbillTestSuiteWithEmbeddedDB extends GuicyKillbillTestSuite
@Inject(optional = true)
protected CacheManager cacheManager;
+ @Nullable
+ @Inject(optional = true)
+ @Named(REDIS_CACHE_CLIENT)
+ protected RedissonClient redissonCachingClient;
+
@BeforeSuite(groups = "slow")
public void beforeSuite() throws Exception {
// Hack to configure log4jdbc -- properties used by tests will be properly setup in @BeforeClass
@@ -118,6 +125,10 @@ public class GuicyKillbillTestSuiteWithEmbeddedDB extends GuicyKillbillTestSuite
cacheManager.close();
}
+ if (redissonCachingClient != null) {
+ redissonCachingClient.shutdown();
+ }
+
try {
DBTestingHelper.get().getInstance().stop();
} catch (final Exception ignored) {