killbill-memoizeit

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);
             }