Details
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java
index 68aa3a4..e9af063 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java
@@ -47,6 +47,8 @@ import org.joda.time.DateTimeZone;
import org.killbill.billing.ErrorCode;
import org.killbill.billing.ObjectType;
import org.killbill.billing.account.api.AccountUserApi;
+import org.killbill.billing.account.api.ImmutableAccountData;
+import org.killbill.billing.catalog.api.Catalog;
import org.killbill.billing.invoice.api.InvoiceApiException;
import org.killbill.billing.invoice.api.InvoiceUserApi;
import org.killbill.billing.jaxrs.json.AdminPaymentJson;
@@ -67,9 +69,11 @@ import org.killbill.billing.util.api.CustomFieldUserApi;
import org.killbill.billing.util.api.RecordIdApi;
import org.killbill.billing.util.api.TagUserApi;
import org.killbill.billing.util.cache.Cachable.CacheType;
+import org.killbill.billing.util.cache.CacheController;
import org.killbill.billing.util.cache.CacheControllerDispatcher;
import org.killbill.billing.util.callcontext.CallContext;
import org.killbill.billing.util.callcontext.TenantContext;
+import org.killbill.billing.util.config.tenant.PerTenantConfig;
import org.killbill.billing.util.entity.Pagination;
import org.killbill.billing.util.tag.Tag;
import org.killbill.billing.util.tag.dao.SystemTags;
@@ -349,13 +353,16 @@ public class AdminResource extends JaxRsResourceBase {
final Long accountRecordId = recordIdApi.getRecordId(accountId, ObjectType.ACCOUNT, tenantContext);
// clear account-record-id cache by accountId (note: String!)
- cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_RECORD_ID).remove(accountIdStr);
+ final CacheController<String, Long> accountRecordIdCacheController = cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_RECORD_ID);
+ accountRecordIdCacheController.remove(accountIdStr);
// clear account-immutable cache by account record id
- cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_IMMUTABLE).remove(accountRecordId);
+ final CacheController<Long, ImmutableAccountData> accountImmutableCacheController = cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_IMMUTABLE);
+ accountImmutableCacheController.remove(accountRecordId);
// clear account-bcd cache by accountId (note: UUID!)
- cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_BCD).remove(accountId);
+ final CacheController<UUID, Integer> accountBCDCacheController = cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_BCD);
+ accountBCDCacheController.remove(accountId);
return Response.status(Status.OK).build();
}
@@ -376,33 +383,40 @@ public class AdminResource extends JaxRsResourceBase {
// getting Tenant Record Id
final Long tenantRecordId = recordIdApi.getRecordId(tenantContext.getTenantId(), ObjectType.TENANT, tenantContext);
- final Function<Object, Boolean> tenantKeysMatcher = new Function<Object, Boolean>() {
+ final Function<String, Boolean> tenantKeysMatcher = new Function<String, Boolean>() {
@Override
- public Boolean apply(@Nullable final Object key) {
- return key != null && key.toString().endsWith("::" + tenantRecordId);
+ public Boolean apply(@Nullable final String key) {
+ return key != null && key.endsWith("::" + tenantRecordId);
}
};
// clear tenant-record-id cache by tenantId
- cacheControllerDispatcher.getCacheController(CacheType.TENANT_RECORD_ID).remove(currentTenant.getId().toString());
+ final CacheController<String, Long> tenantRecordIdCacheController = cacheControllerDispatcher.getCacheController(CacheType.TENANT_RECORD_ID);
+ tenantRecordIdCacheController.remove(currentTenant.getId().toString());
// clear tenant-payment-state-machine-config cache by tenantRecordId
- cacheControllerDispatcher.getCacheController(CacheType.TENANT_PAYMENT_STATE_MACHINE_CONFIG).remove(tenantKeysMatcher);
+ final CacheController<String, Object> tenantPaymentStateMachineConfigCacheController = cacheControllerDispatcher.getCacheController(CacheType.TENANT_PAYMENT_STATE_MACHINE_CONFIG);
+ tenantPaymentStateMachineConfigCacheController.remove(tenantKeysMatcher);
// clear tenant cache by tenantApiKey
- cacheControllerDispatcher.getCacheController(CacheType.TENANT).remove(currentTenant.getApiKey());
+ final CacheController<String, Tenant> tenantCacheController = cacheControllerDispatcher.getCacheController(CacheType.TENANT);
+ tenantCacheController.remove(currentTenant.getApiKey());
// clear tenant-kv cache by tenantRecordId
- cacheControllerDispatcher.getCacheController(CacheType.TENANT_KV).remove(tenantKeysMatcher);
+ final CacheController<String, String> tenantKVCacheController = cacheControllerDispatcher.getCacheController(CacheType.TENANT_KV);
+ tenantKVCacheController.remove(tenantKeysMatcher);
// clear tenant-config cache by tenantRecordId
- cacheControllerDispatcher.getCacheController(CacheType.TENANT_CONFIG).remove(tenantRecordId);
+ final CacheController<Long, PerTenantConfig> tenantConfigCacheController = cacheControllerDispatcher.getCacheController(CacheType.TENANT_CONFIG);
+ tenantConfigCacheController.remove(tenantRecordId);
// clear tenant-overdue-config cache by tenantRecordId
- cacheControllerDispatcher.getCacheController(CacheType.TENANT_OVERDUE_CONFIG).remove(tenantRecordId);
+ final CacheController<Long, Object> tenantOverdueConfigCacheController = cacheControllerDispatcher.getCacheController(CacheType.TENANT_OVERDUE_CONFIG);
+ tenantOverdueConfigCacheController.remove(tenantRecordId);
// clear tenant-catalog cache by tenantRecordId
- cacheControllerDispatcher.getCacheController(CacheType.TENANT_CATALOG).remove(tenantRecordId);
+ final CacheController<Long, Catalog> tenantCatalogCacheController = cacheControllerDispatcher.getCacheController(CacheType.TENANT_CATALOG);
+ tenantCatalogCacheController.remove(tenantRecordId);
return Response.status(Status.OK).build();
}
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCache.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCache.java
index da340aa..c00915a 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCache.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCache.java
@@ -16,11 +16,13 @@
package org.killbill.billing.jaxrs;
-import java.util.List;
import java.util.UUID;
import org.joda.time.LocalDate;
+import org.killbill.automaton.StateMachineConfig;
+import org.killbill.billing.account.api.ImmutableAccountData;
import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.Catalog;
import org.killbill.billing.catalog.api.PriceListSet;
import org.killbill.billing.catalog.api.ProductCategory;
import org.killbill.billing.client.RequestOptions;
@@ -29,13 +31,14 @@ import org.killbill.billing.client.model.PaymentMethod;
import org.killbill.billing.client.model.PaymentMethodPluginDetail;
import org.killbill.billing.client.model.Subscription;
import org.killbill.billing.client.model.Tenant;
+import org.killbill.billing.overdue.api.OverdueConfig;
import org.killbill.billing.util.cache.Cachable.CacheType;
+import org.killbill.billing.util.cache.CacheController;
+import org.killbill.billing.util.config.tenant.PerTenantConfig;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.google.common.io.Resources;
-import net.sf.ehcache.Ehcache;
-import net.sf.ehcache.Element;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
@@ -46,31 +49,31 @@ public class TestCache extends TestJaxrsBase {
@Test(groups = "slow", description = "Can Invalidate (clear) a Cache by name")
public void testInvalidateCacheByName() throws Exception {
// get Ehcache item with name "record-id"
- final Ehcache cache = cacheManager.getEhcache(CacheType.RECORD_ID.getCacheName());
+ final CacheController<String, Long> cache = cacheControllerDispatcher.getCacheController(CacheType.RECORD_ID);
// verify that it is not null and has one stored key (the default tenant created for all integration tests)
assertNotNull(cache);
- Assert.assertEquals(cache.getSize(), 1);
+ Assert.assertEquals(cache.size(), 1);
// invalidate the specified cache
- killBillClient.invalidateCacheByName(cache.getName(), requestOptions);
+ killBillClient.invalidateCacheByName(CacheType.RECORD_ID.getCacheName(), requestOptions);
// verify that now the cache is empty and has no keys stored
- Assert.assertEquals(cache.getSize(), 0);
+ Assert.assertEquals(cache.size(), 0);
}
@Test(groups = "slow", description = "Can Invalidate (clear) all available Caches")
public void testInvalidateAllCaches() throws Exception {
// get Ehcache item with name "record-id"
- final Ehcache cache = cacheManager.getEhcache(CacheType.RECORD_ID.getCacheName());
+ final CacheController<String, Long> cache = cacheControllerDispatcher.getCacheController(CacheType.RECORD_ID);
// verify that it is not null and has one stored key (the default tenant created for all integration tests)
assertNotNull(cache);
- Assert.assertEquals(cache.getSize(), 1);
+ Assert.assertEquals(cache.size(), 1);
// invalidate all caches
killBillClient.invalidateAllCaches(requestOptions);
// verify that now the cache is empty and has no keys stored
- Assert.assertEquals(cache.getSize(), 0);
+ Assert.assertEquals(cache.size(), 0);
}
@Test(groups = "slow", description = "Can Invalidate (clear) all Account Caches by accountId")
@@ -78,27 +81,23 @@ public class TestCache extends TestJaxrsBase {
final Account input = createAccountNoPMBundleAndSubscription();
// get all caches per account level
- final Ehcache accountRecordIdCache = cacheManager.getEhcache(CacheType.ACCOUNT_RECORD_ID.getCacheName());
- final Ehcache accountImmutableCache = cacheManager.getEhcache(CacheType.ACCOUNT_IMMUTABLE.getCacheName());
- final Ehcache accountBcdCache = cacheManager.getEhcache(CacheType.ACCOUNT_BCD.getCacheName());
+ final CacheController<String, Long> accountRecordIdCache = cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_RECORD_ID);
+ final CacheController<Long, ImmutableAccountData> accountImmutableCache = cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_IMMUTABLE);
+ final CacheController<UUID, Integer> accountBcdCache = cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_BCD);
// verify that they are not null and have the accountId stored as a key (the account created before)
- assertNotNull(accountRecordIdCache);
- final Element accountRecordIdElement = accountRecordIdCache.get(input.getAccountId().toString());
- assertNotNull(accountRecordIdElement);
- final Long accountRecordId = (Long) accountRecordIdElement.getObjectValue();
- assertNotNull(accountImmutableCache);
- assertNotNull(accountImmutableCache.get(accountRecordId));
- assertNotNull(accountBcdCache);
- assertNotNull(accountBcdCache.get(input.getAccountId()));
+ assertTrue(accountRecordIdCache.isKeyInCache(input.getAccountId().toString()));
+ final Long accountRecordId = accountRecordIdCache.get(input.getAccountId().toString(), null);
+ assertTrue(accountImmutableCache.isKeyInCache(accountRecordId));
+ assertTrue(accountBcdCache.isKeyInCache(input.getAccountId()));
// invalidate caches per account level by accountId
killBillClient.invalidateCacheByAccount(input.getAccountId().toString(), requestOptions);
// verify that now the caches don't have the accountId key stored
- Assert.assertNull(accountRecordIdCache.get(input.getAccountId().toString()));
- Assert.assertNull(accountImmutableCache.get(accountRecordId));
- Assert.assertNull(accountBcdCache.get(input.getAccountId()));
+ Assert.assertFalse(accountRecordIdCache.isKeyInCache(input.getAccountId().toString()));
+ Assert.assertFalse(accountImmutableCache.isKeyInCache(accountRecordId));
+ Assert.assertFalse(accountBcdCache.isKeyInCache(input.getAccountId()));
}
@Test(groups = "slow", description = "Can Invalidate (clear) all Tenant Caches for current Tenant")
@@ -128,48 +127,40 @@ public class TestCache extends TestJaxrsBase {
createAccountWithPMBundleAndSubscriptionAndWaitForFirstInvoiceWithInputOptions(inputOptions);
// get all caches per tenant level
- final Ehcache tenantRecordIdCache = cacheManager.getEhcache(CacheType.TENANT_RECORD_ID.getCacheName());
- final Ehcache tenantPaymentStateMachineConfigCache = cacheManager.getEhcache(CacheType.TENANT_PAYMENT_STATE_MACHINE_CONFIG.getCacheName());
- final Ehcache tenantCache = cacheManager.getEhcache(CacheType.TENANT.getCacheName());
- final Ehcache tenantKvCache = cacheManager.getEhcache(CacheType.TENANT_KV.getCacheName());
- final Ehcache tenantConfigCache = cacheManager.getEhcache(CacheType.TENANT_CONFIG.getCacheName());
- final Ehcache tenantOverdueConfigCache = cacheManager.getEhcache(CacheType.TENANT_OVERDUE_CONFIG.getCacheName());
- final Ehcache tenantCatalogCache = cacheManager.getEhcache(CacheType.TENANT_CATALOG.getCacheName());
-
- // getting current Tenant's record Id from the specific Cache
- Long tenantRecordId = (Long) tenantRecordIdCache.get(currentTenant.getTenantId().toString()).getObjectValue();
+ final CacheController<String, Long> tenantRecordIdCache = cacheControllerDispatcher.getCacheController(CacheType.TENANT_RECORD_ID);
+ final CacheController<String, StateMachineConfig> tenantPaymentStateMachineConfigCache = cacheControllerDispatcher.getCacheController(CacheType.TENANT_PAYMENT_STATE_MACHINE_CONFIG);
+ final CacheController<String, org.killbill.billing.tenant.api.Tenant> tenantCache = cacheControllerDispatcher.getCacheController(CacheType.TENANT);
+ final CacheController<String, String> tenantKvCache = cacheControllerDispatcher.getCacheController(CacheType.TENANT_KV);
+ final CacheController<Long, PerTenantConfig> tenantConfigCache = cacheControllerDispatcher.getCacheController(CacheType.TENANT_CONFIG);
+ final CacheController<Long, OverdueConfig> tenantOverdueConfigCache = cacheControllerDispatcher.getCacheController(CacheType.TENANT_OVERDUE_CONFIG);
+ final CacheController<Long, Catalog> tenantCatalogCache = cacheControllerDispatcher.getCacheController(CacheType.TENANT_CATALOG);
// verify that they are not null and have the expected tenant information
- assertNotNull(tenantRecordIdCache);
- assertNotNull(tenantRecordIdCache.get(currentTenant.getTenantId().toString()));
- assertNotNull(tenantPaymentStateMachineConfigCache);
+ assertTrue(tenantRecordIdCache.isKeyInCache(currentTenant.getTenantId().toString()));
+ final Long tenantRecordId = tenantRecordIdCache.get(currentTenant.getTenantId().toString(), null);
+
assertTrue(hasKeysByTenantRecordId(tenantPaymentStateMachineConfigCache, tenantRecordId.toString()));
- assertNotNull(tenantCache);
- assertNotNull(tenantCache.get(testApiKey));
- assertNotNull(tenantKvCache);
+ assertTrue(tenantCache.isKeyInCache(testApiKey));
assertTrue(hasKeysByTenantRecordId(tenantKvCache, tenantRecordId.toString()));
- assertNotNull(tenantConfigCache);
- assertNotNull(tenantConfigCache.get(tenantRecordId));
- assertNotNull(tenantOverdueConfigCache);
- assertNotNull(tenantOverdueConfigCache.get(tenantRecordId));
- assertNotNull(tenantCatalogCache);
- assertNotNull(tenantCatalogCache.get(tenantRecordId));
+ assertTrue(tenantConfigCache.isKeyInCache(tenantRecordId));
+ assertTrue(tenantOverdueConfigCache.isKeyInCache(tenantRecordId));
+ assertTrue(tenantCatalogCache.isKeyInCache(tenantRecordId));
// invalidate caches per tenant level
killBillClient.invalidateCacheByTenant(inputOptions);
// verify that now the caches don't have the previous values
- Assert.assertNull(tenantRecordIdCache.get(currentTenant.getTenantId().toString()));
+ assertFalse(tenantRecordIdCache.isKeyInCache(currentTenant.getTenantId().toString()));
assertFalse(hasKeysByTenantRecordId(tenantPaymentStateMachineConfigCache, tenantRecordId.toString()));
- Assert.assertNull(tenantCache.get(testApiKey));
+ assertFalse(tenantCache.isKeyInCache(testApiKey));
assertFalse(hasKeysByTenantRecordId(tenantKvCache, tenantRecordId.toString()));
- Assert.assertNull(tenantConfigCache.get(tenantRecordId));
- Assert.assertNull(tenantOverdueConfigCache.get(tenantRecordId));
- Assert.assertNull(tenantCatalogCache.get(tenantRecordId));
+ assertFalse(tenantConfigCache.isKeyInCache(tenantRecordId));
+ assertFalse(tenantOverdueConfigCache.isKeyInCache(tenantRecordId));
+ assertFalse(tenantCatalogCache.isKeyInCache(tenantRecordId));
}
- private boolean hasKeysByTenantRecordId(final Ehcache tenantCache, final String tenantRecordId) {
- for (String key : (List<String>) tenantCache.getKeys()) {
+ private boolean hasKeysByTenantRecordId(final CacheController<String, ?> tenantCache, final String tenantRecordId) {
+ for (final String key : tenantCache.getKeys()) {
if (key.endsWith("::" + tenantRecordId)) {
return true;
}
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java
index d4ec7bf..66007ef 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java
@@ -1,7 +1,7 @@
/*
* Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2015 Groupon, Inc
- * Copyright 2014-2015 The Billing Project, LLC
+ * Copyright 2014-2017 Groupon, Inc
+ * Copyright 2014-2017 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
@@ -74,7 +74,6 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.inject.Module;
import com.google.inject.util.Modules;
-import net.sf.ehcache.CacheManager;
public class TestJaxrsBase extends KillbillClient {
@@ -107,9 +106,6 @@ public class TestJaxrsBase extends KillbillClient {
@Inject
protected TenantCacheInvalidation tenantCacheInvalidation;
- @Inject
- protected CacheManager cacheManager;
-
protected DaoConfig daoConfig;
protected KillbillServerConfig serverConfig;
diff --git a/util/src/main/java/org/killbill/billing/util/cache/CacheController.java b/util/src/main/java/org/killbill/billing/util/cache/CacheController.java
index 137c301..46ee5dc 100644
--- a/util/src/main/java/org/killbill/billing/util/cache/CacheController.java
+++ b/util/src/main/java/org/killbill/billing/util/cache/CacheController.java
@@ -16,12 +16,18 @@
package org.killbill.billing.util.cache;
+import java.util.List;
+
import org.killbill.billing.util.cache.Cachable.CacheType;
import com.google.common.base.Function;
public interface CacheController<K, V> {
+ List<K> getKeys();
+
+ boolean isKeyInCache(K key);
+
V get(K key, CacheLoaderArgument objectType);
boolean remove(K key);
diff --git a/util/src/main/java/org/killbill/billing/util/cache/EhCacheBasedCacheController.java b/util/src/main/java/org/killbill/billing/util/cache/EhCacheBasedCacheController.java
index dc11ba6..27d2326 100644
--- a/util/src/main/java/org/killbill/billing/util/cache/EhCacheBasedCacheController.java
+++ b/util/src/main/java/org/killbill/billing/util/cache/EhCacheBasedCacheController.java
@@ -20,6 +20,7 @@ package org.killbill.billing.util.cache;
import java.util.Collection;
import java.util.HashSet;
+import java.util.List;
import org.killbill.billing.util.cache.Cachable.CacheType;
import org.slf4j.Logger;
@@ -43,11 +44,21 @@ public class EhCacheBasedCacheController<K, V> implements CacheController<K, V>
}
@Override
+ public List<K> getKeys() {
+ return cache.getKeys();
+ }
+
+ @Override
+ public boolean isKeyInCache(final K key) {
+ return cache.isKeyInCache(key);
+ }
+
+ @Override
public V get(final K key, final CacheLoaderArgument cacheLoaderArgument) {
checkKey(key);
final V value;
- if (!cache.isKeyInCache(key)) {
+ if (!isKeyInCache(key)) {
value = computeAndCacheValue(key, cacheLoaderArgument);
} else {
final Element element = cache.get(key);
@@ -78,7 +89,7 @@ public class EhCacheBasedCacheController<K, V> implements CacheController<K, V>
@Override
public boolean remove(final K key) {
checkKey(key);
- if (cache.isKeyInCache(key)) {
+ if (isKeyInCache(key)) {
cache.remove(key);
return true;
} else {
@@ -89,7 +100,7 @@ public class EhCacheBasedCacheController<K, V> implements CacheController<K, V>
@Override
public void remove(final Function<K, Boolean> keyMatcher) {
final Collection<K> toRemove = new HashSet<K>();
- for (final Object key : cache.getKeys()) {
+ for (final Object key : getKeys()) {
if (keyMatcher.apply((K) key) == Boolean.TRUE) {
toRemove.add((K) key);
}