killbill-memoizeit

overdue: use the tenantRecordId as the overdue cache key Signed-off-by:

1/25/2015 7:59:21 PM

Details

diff --git a/overdue/src/main/java/org/killbill/billing/overdue/caching/EhCacheOverdueConfigCache.java b/overdue/src/main/java/org/killbill/billing/overdue/caching/EhCacheOverdueConfigCache.java
index dc998c9..2624064 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/caching/EhCacheOverdueConfigCache.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/caching/EhCacheOverdueConfigCache.java
@@ -1,6 +1,6 @@
 /*
- * Copyright 2014 Groupon, Inc
- * Copyright 2014 The Billing Project, LLC
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 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
@@ -66,7 +66,7 @@ public class EhCacheOverdueConfigCache implements OverdueConfigCache {
                 defaultOverdueConfig = XMLLoader.getObjectFromUri(u, DefaultOverdueConfig.class);
                 missingOrCorruptedDefaultConfig = (defaultOverdueConfig == null);
             }
-        } catch (Exception e) {
+        } catch (final Exception e) {
             missingOrCorruptedDefaultConfig = true;
             log.warn("Exception loading default overdue config from " + configURI, e);
         }
@@ -83,40 +83,40 @@ public class EhCacheOverdueConfigCache implements OverdueConfigCache {
 
     @Override
     public OverdueConfig getOverdueConfig(final InternalTenantContext tenantContext) throws OverdueApiException {
-
         if (tenantContext.getTenantRecordId() == InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID) {
+            if (defaultOverdueConfig == null) {
+                throw new OverdueApiException(ErrorCode.OVERDUE_NOT_CONFIGURED);
+            }
             return defaultOverdueConfig;
         }
         // The cache loader might choke on some bad xml -- unlikely since we check its validity prior storing it,
         // but to be on the safe side;;
         try {
-            final OverdueConfig overdueConfig = (OverdueConfig) cacheController.get(tenantContext, cacheLoaderArgument);
+            final OverdueConfig overdueConfig = (OverdueConfig) cacheController.get(tenantContext.getTenantRecordId(), cacheLoaderArgument);
             return (overdueConfig != null) ? overdueConfig : defaultOverdueConfig;
-        } catch (IllegalStateException e) {
+        } catch (final IllegalStateException e) {
             throw new OverdueApiException(ErrorCode.OVERDUE_INVALID_FOR_TENANT, tenantContext.getTenantRecordId());
         }
     }
 
     @Override
     public void clearOverdueConfig(final InternalTenantContext tenantContext) {
-
-        if (tenantContext.getTenantRecordId() == InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID) {
-            return;
+        if (tenantContext.getTenantRecordId() != InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID) {
+            cacheController.remove(tenantContext.getTenantRecordId());
         }
-        cacheController.remove(tenantContext);
     }
 
     private CacheLoaderArgument initializeCacheLoaderArgument() {
         final LoaderCallback loaderCallback = new LoaderCallback() {
             @Override
-            public Object loadCatalog(final String catalogXMLs) throws OverdueApiException {
-                final InputStream overdueConfigStream = new ByteArrayInputStream(catalogXMLs.getBytes());
+            public Object loadOverdueConfig(final String overdueConfigXML) throws OverdueApiException {
+                final InputStream overdueConfigStream = new ByteArrayInputStream(overdueConfigXML.getBytes());
                 final URI uri;
                 try {
                     uri = new URI("/overdueConfig");
                     final DefaultOverdueConfig overdueConfig = XMLLoader.getObjectFromStream(uri, overdueConfigStream, DefaultOverdueConfig.class);
                     return overdueConfig;
-                } catch (Exception e) {
+                } catch (final Exception e) {
                     throw new OverdueApiException(ErrorCode.OVERDUE_INVALID_FOR_TENANT, "Problem encountered loading overdue config ", e);
                 }
             }
diff --git a/overdue/src/test/java/org/killbill/billing/overdue/caching/TestEhCacheOverdueConfigCache.java b/overdue/src/test/java/org/killbill/billing/overdue/caching/TestEhCacheOverdueConfigCache.java
new file mode 100644
index 0000000..1cb8c1b
--- /dev/null
+++ b/overdue/src/test/java/org/killbill/billing/overdue/caching/TestEhCacheOverdueConfigCache.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2015 Groupon, Inc
+ * Copyright 2015 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.overdue.caching;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.killbill.billing.callcontext.InternalCallContext;
+import org.killbill.billing.callcontext.InternalTenantContext;
+import org.killbill.billing.overdue.OverdueTestSuiteNoDB;
+import org.killbill.billing.overdue.api.OverdueApiException;
+import org.killbill.billing.overdue.api.OverdueConfig;
+import org.killbill.xmlloader.UriAccessor;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.io.CharStreams;
+import com.google.common.io.Resources;
+
+public class TestEhCacheOverdueConfigCache extends OverdueTestSuiteNoDB {
+
+    private InternalTenantContext multiTenantContext;
+    private InternalTenantContext otherMultiTenantContext;
+
+    @BeforeMethod(groups = "fast")
+    public void beforeMethod() throws Exception {
+        super.beforeMethod();
+
+        cacheControllerDispatcher.clearAll();
+
+        multiTenantContext = Mockito.mock(InternalTenantContext.class);
+        Mockito.when(multiTenantContext.getAccountRecordId()).thenReturn(456L);
+        Mockito.when(multiTenantContext.getTenantRecordId()).thenReturn(99L);
+
+        otherMultiTenantContext = Mockito.mock(InternalCallContext.class);
+        Mockito.when(otherMultiTenantContext.getAccountRecordId()).thenReturn(123L);
+        Mockito.when(otherMultiTenantContext.getTenantRecordId()).thenReturn(112233L);
+    }
+
+    //
+    // Verify the default OverdueConfig is returned when used in mono-tenant and overdue system property has not been set
+    //
+    @Test(groups = "fast")
+    public void testMissingDefaultOverdueConfig() throws OverdueApiException {
+        overdueConfigCache.loadDefaultOverdueConfig((String) null);
+        final OverdueConfig result = overdueConfigCache.getOverdueConfig(internalCallContext);
+        Assert.assertNotNull(result);
+        Assert.assertEquals(result.getOverdueStatesAccount().getStates().length, 0);
+    }
+
+    //
+    // Verify the default OverdueConfig is returned when system property has been set (and OverdueConfigCache has been initialized)
+    //
+    @Test(groups = "fast")
+    public void testDefaultOverdueConfig() throws OverdueApiException {
+        overdueConfigCache.loadDefaultOverdueConfig(Resources.getResource("OverdueConfig.xml").toExternalForm());
+
+        final OverdueConfig result = overdueConfigCache.getOverdueConfig(internalCallContext);
+        Assert.assertNotNull(result);
+        Assert.assertEquals(result.getOverdueStatesAccount().getStates().length, 1);
+        Assert.assertTrue(result.getOverdueStatesAccount().getStates()[0].isClearState());
+
+        // Verify the lookup with other contexts
+        Assert.assertEquals(overdueConfigCache.getOverdueConfig(multiTenantContext), result);
+        Assert.assertEquals(overdueConfigCache.getOverdueConfig(otherMultiTenantContext), result);
+        Assert.assertEquals(overdueConfigCache.getOverdueConfig(Mockito.mock(InternalTenantContext.class)), result);
+        Assert.assertEquals(overdueConfigCache.getOverdueConfig(Mockito.mock(InternalCallContext.class)), result);
+    }
+
+    //
+    // Verify OverdueConfigCache returns per tenant overdue config:
+    // 1. We first mock TenantInternalApi to return a different overdue config than the default one
+    // 2. We then mock TenantInternalApi to throw RuntimeException which means overdue config was cached and there was no additional call
+    //    to the TenantInternalApi api (otherwise test would fail with RuntimeException)
+    //
+    @Test(groups = "fast")
+    public void testExistingTenantOverdue() throws OverdueApiException, URISyntaxException, IOException {
+        final AtomicBoolean shouldThrow = new AtomicBoolean(false);
+        final Long multiTenantRecordId = multiTenantContext.getTenantRecordId();
+        overdueConfigCache.loadDefaultOverdueConfig(Resources.getResource("OverdueConfig.xml").toExternalForm());
+
+        final InputStream tenantInputOverdueConfig = UriAccessor.accessUri(new URI(Resources.getResource("OverdueConfig2.xml").toExternalForm()));
+        final String tenantOverdueConfigXML = CharStreams.toString(new InputStreamReader(tenantInputOverdueConfig, "UTF-8"));
+        final InputStream otherTenantInputOverdueConfig = UriAccessor.accessUri(new URI(Resources.getResource("OverdueConfig.xml").toExternalForm()));
+        final String otherTenantOverdueConfigXML = CharStreams.toString(new InputStreamReader(otherTenantInputOverdueConfig, "UTF-8"));
+        Mockito.when(tenantInternalApi.getTenantOverdueConfig(Mockito.any(InternalTenantContext.class))).thenAnswer(new Answer<String>() {
+            @Override
+            public String answer(final InvocationOnMock invocation) throws Throwable {
+                if (shouldThrow.get()) {
+                    throw new RuntimeException();
+                }
+                final InternalTenantContext internalContext = (InternalTenantContext) invocation.getArguments()[0];
+                if (multiTenantRecordId.equals(internalContext.getTenantRecordId())) {
+                    return tenantOverdueConfigXML;
+                } else {
+                    return otherTenantOverdueConfigXML;
+                }
+            }
+        });
+
+        // Verify the lookup for this tenant
+        final OverdueConfig result = overdueConfigCache.getOverdueConfig(multiTenantContext);
+        Assert.assertNotNull(result);
+        Assert.assertEquals(result.getOverdueStatesAccount().getStates().length, 1);
+        Assert.assertFalse(result.getOverdueStatesAccount().getStates()[0].isClearState());
+
+        // Verify the lookup for another tenant
+        final OverdueConfig otherResult = overdueConfigCache.getOverdueConfig(otherMultiTenantContext);
+        Assert.assertNotNull(otherResult);
+        Assert.assertEquals(otherResult.getOverdueStatesAccount().getStates().length, 1);
+        Assert.assertTrue(otherResult.getOverdueStatesAccount().getStates()[0].isClearState());
+
+        shouldThrow.set(true);
+
+        // Verify the lookup for this tenant
+        final OverdueConfig result2 = overdueConfigCache.getOverdueConfig(multiTenantContext);
+        Assert.assertEquals(result2, result);
+
+        // Verify the lookup with another context for the same tenant
+        final InternalCallContext sameMultiTenantContext = Mockito.mock(InternalCallContext.class);
+        Mockito.when(sameMultiTenantContext.getAccountRecordId()).thenReturn(9102L);
+        Mockito.when(sameMultiTenantContext.getTenantRecordId()).thenReturn(multiTenantRecordId);
+        Assert.assertEquals(overdueConfigCache.getOverdueConfig(sameMultiTenantContext), result);
+
+        // Verify the lookup with the other tenant
+        Assert.assertEquals(overdueConfigCache.getOverdueConfig(otherMultiTenantContext), otherResult);
+    }
+}
diff --git a/overdue/src/test/java/org/killbill/billing/overdue/OverdueTestSuiteNoDB.java b/overdue/src/test/java/org/killbill/billing/overdue/OverdueTestSuiteNoDB.java
index 4bb38a8..8e90891 100644
--- a/overdue/src/test/java/org/killbill/billing/overdue/OverdueTestSuiteNoDB.java
+++ b/overdue/src/test/java/org/killbill/billing/overdue/OverdueTestSuiteNoDB.java
@@ -1,7 +1,7 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
- * Copyright 2014 Groupon, Inc
- * Copyright 2014 The Billing Project, LLC
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 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
@@ -27,6 +27,8 @@ import org.killbill.billing.junction.BlockingInternalApi;
 import org.killbill.billing.lifecycle.api.BusService;
 import org.killbill.billing.overdue.applicator.OverdueBusListenerTester;
 import org.killbill.billing.overdue.applicator.OverdueStateApplicator;
+import org.killbill.billing.overdue.caching.OverdueCacheInvalidationCallback;
+import org.killbill.billing.overdue.caching.OverdueConfigCache;
 import org.killbill.billing.overdue.calculator.BillingStateCalculator;
 import org.killbill.billing.overdue.glue.DefaultOverdueModule;
 import org.killbill.billing.overdue.glue.TestOverdueModuleNoDB;
@@ -34,6 +36,8 @@ import org.killbill.billing.overdue.notification.OverdueNotifier;
 import org.killbill.billing.overdue.notification.OverduePoster;
 import org.killbill.billing.overdue.service.DefaultOverdueService;
 import org.killbill.billing.overdue.wrapper.OverdueWrapperFactory;
+import org.killbill.billing.tenant.api.TenantInternalApi;
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
 import org.killbill.billing.util.callcontext.InternalCallContextFactory;
 import org.killbill.bus.api.PersistentBus;
 import org.killbill.notificationq.api.NotificationQueueService;
@@ -89,6 +93,14 @@ public abstract class OverdueTestSuiteNoDB extends GuicyKillbillTestSuiteNoDB {
     protected OverdueWrapperFactory overdueWrapperFactory;
     @Inject
     protected TestOverdueHelper testOverdueHelper;
+    @Inject
+    protected CacheControllerDispatcher cacheControllerDispatcher;
+    @Inject
+    protected OverdueConfigCache overdueConfigCache;
+    @Inject
+    protected OverdueCacheInvalidationCallback cacheInvalidationCallback;
+    @Inject
+    protected TenantInternalApi tenantInternalApi;
 
     @BeforeClass(groups = "fast")
     protected void beforeClass() throws Exception {
diff --git a/overdue/src/test/resources/OverdueConfig.xml b/overdue/src/test/resources/OverdueConfig.xml
index 913ed9d..40ad9a3 100644
--- a/overdue/src/test/resources/OverdueConfig.xml
+++ b/overdue/src/test/resources/OverdueConfig.xml
@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
   ~ Copyright 2010-2013 Ning, Inc.
+  ~ Copyright 2014-2015 Groupon, Inc
+  ~ Copyright 2014-2015 The Billing Project, LLC
   ~
-  ~ Ning licenses this file to you under the Apache License, version 2.0
+  ~ 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:
   ~
@@ -16,11 +18,11 @@
   -->
 
 <overdueConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:noNamespaceSchemaLocation="CatalogSchema.xsd ">
-	<accountOverdueStates>
-		<state name="Clear">
-			<isClearState>true</isClearState>
-		</state>
-	</accountOverdueStates>
+               xsi:noNamespaceSchemaLocation="OverdueConfigSchema.xsd ">
+    <accountOverdueStates>
+        <state name="Clear">
+            <isClearState>true</isClearState>
+        </state>
+    </accountOverdueStates>
 </overdueConfig>
 
diff --git a/overdue/src/test/resources/OverdueConfig2.xml b/overdue/src/test/resources/OverdueConfig2.xml
new file mode 100644
index 0000000..1d9ec5b
--- /dev/null
+++ b/overdue/src/test/resources/OverdueConfig2.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2015 Groupon, Inc
+  ~ Copyright 2015 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.
+  -->
+
+<overdueConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+               xsi:noNamespaceSchemaLocation="OverdueConfigSchema.xsd ">
+    <accountOverdueStates>
+        <state name="Overdue">
+            <isClearState>false</isClearState>
+        </state>
+    </accountOverdueStates>
+</overdueConfig>
+
diff --git a/overdue/src/test/resources/OverdueConfigSchema.xsd b/overdue/src/test/resources/OverdueConfigSchema.xsd
index bf57ece..d8f014b 100644
--- a/overdue/src/test/resources/OverdueConfigSchema.xsd
+++ b/overdue/src/test/resources/OverdueConfigSchema.xsd
@@ -1,11 +1,11 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0">
-<xs:element name="overdueConfig" type="overdueConfig"/>
-<xs:complexType name="overdueConfig">
+<xs:element name="overdueConfig" type="defaultOverdueConfig"/>
+<xs:complexType name="defaultOverdueConfig">
 <xs:complexContent>
 <xs:extension base="validatingConfig">
 <xs:sequence>
-<xs:element name="bundleOverdueStates" type="overdueStatesBundle"/>
+<xs:element name="accountOverdueStates" type="defaultOverdueStatesAccount"/>
 </xs:sequence>
 </xs:extension>
 </xs:complexContent>
@@ -13,10 +13,11 @@
 <xs:complexType abstract="true" name="validatingConfig">
 <xs:sequence/>
 </xs:complexType>
-<xs:complexType name="overdueStatesBundle">
+<xs:complexType name="defaultOverdueStatesAccount">
 <xs:complexContent>
 <xs:extension base="defaultOverdueStateSet">
 <xs:sequence>
+<xs:element minOccurs="0" name="initialReevaluationInterval" type="defaultDuration"/>
 <xs:element maxOccurs="unbounded" name="state" type="defaultOverdueState"/>
 </xs:sequence>
 </xs:extension>
@@ -29,23 +30,34 @@
 </xs:extension>
 </xs:complexContent>
 </xs:complexType>
+<xs:complexType name="defaultDuration">
+<xs:complexContent>
+<xs:extension base="validatingConfig">
+<xs:sequence>
+<xs:element name="unit" type="timeUnit"/>
+<xs:element minOccurs="0" name="number" type="xs:int"/>
+</xs:sequence>
+</xs:extension>
+</xs:complexContent>
+</xs:complexType>
 <xs:complexType name="defaultOverdueState">
 <xs:complexContent>
 <xs:extension base="validatingConfig">
 <xs:sequence>
-<xs:element minOccurs="0" name="condition" type="defaultCondition"/>
+<xs:element minOccurs="0" name="condition" type="defaultOverdueCondition"/>
 <xs:element minOccurs="0" name="externalMessage" type="xs:string"/>
 <xs:element minOccurs="0" name="blockChanges" type="xs:boolean"/>
 <xs:element minOccurs="0" name="disableEntitlementAndChangesBlocked" type="xs:boolean"/>
-<xs:element minOccurs="0" name="daysBetweenPaymentRetries" type="xs:int"/>
+<xs:element minOccurs="0" name="subscriptionCancellationPolicy" type="overdueCancellationPolicy"/>
 <xs:element minOccurs="0" name="isClearState" type="xs:boolean"/>
 <xs:element minOccurs="0" name="autoReevaluationInterval" type="defaultDuration"/>
+<xs:element minOccurs="0" name="enterStateEmailNotification" type="defaultEmailNotification"/>
 </xs:sequence>
 <xs:attribute name="name" type="xs:ID" use="required"/>
 </xs:extension>
 </xs:complexContent>
 </xs:complexType>
-<xs:complexType name="defaultCondition">
+<xs:complexType name="defaultOverdueCondition">
 <xs:complexContent>
 <xs:extension base="validatingConfig">
 <xs:sequence>
@@ -64,15 +76,12 @@
 </xs:extension>
 </xs:complexContent>
 </xs:complexType>
-<xs:complexType name="defaultDuration">
-<xs:complexContent>
-<xs:extension base="validatingConfig">
+<xs:complexType name="defaultEmailNotification">
 <xs:sequence>
-<xs:element name="unit" type="timeUnit"/>
-<xs:element minOccurs="0" name="number" type="xs:int"/>
+<xs:element name="subject" type="xs:string"/>
+<xs:element name="templateName" type="xs:string"/>
+<xs:element minOccurs="0" name="isHTML" type="xs:boolean"/>
 </xs:sequence>
-</xs:extension>
-</xs:complexContent>
 </xs:complexType>
 <xs:simpleType name="timeUnit">
 <xs:restriction base="xs:string">
@@ -102,6 +111,16 @@
 <xs:enumeration value="AUTO_INVOICING_OFF"/>
 <xs:enumeration value="OVERDUE_ENFORCEMENT_OFF"/>
 <xs:enumeration value="WRITTEN_OFF"/>
+<xs:enumeration value="MANUAL_PAY"/>
+<xs:enumeration value="TEST"/>
+<xs:enumeration value="PARTNER"/>
+</xs:restriction>
+</xs:simpleType>
+<xs:simpleType name="overdueCancellationPolicy">
+<xs:restriction base="xs:string">
+<xs:enumeration value="END_OF_TERM"/>
+<xs:enumeration value="IMMEDIATE"/>
+<xs:enumeration value="NONE"/>
 </xs:restriction>
 </xs:simpleType>
 </xs:schema>
diff --git a/util/src/main/java/org/killbill/billing/util/cache/TenantOverdueConfigCacheLoader.java b/util/src/main/java/org/killbill/billing/util/cache/TenantOverdueConfigCacheLoader.java
index 7b53bb8..80222ac 100644
--- a/util/src/main/java/org/killbill/billing/util/cache/TenantOverdueConfigCacheLoader.java
+++ b/util/src/main/java/org/killbill/billing/util/cache/TenantOverdueConfigCacheLoader.java
@@ -1,6 +1,6 @@
 /*
- * Copyright 2014 Groupon, Inc
- * Copyright 2014 The Billing Project, LLC
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 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
@@ -23,7 +23,6 @@ import javax.inject.Singleton;
 import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.overdue.api.OverdueApiException;
 import org.killbill.billing.tenant.api.TenantInternalApi;
-import org.killbill.billing.tenant.api.TenantInternalApi.CacheInvalidationCallback;
 import org.killbill.billing.util.cache.Cachable.CacheType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -50,18 +49,19 @@ public class TenantOverdueConfigCacheLoader extends BaseCacheLoader {
     public Object load(final Object key, final Object argument) {
         checkCacheLoaderStatus();
 
-        if (!(key instanceof InternalTenantContext)) {
+        if (!(key instanceof Long)) {
             throw new IllegalArgumentException("Unexpected key type of " + key.getClass().getName());
         }
         if (!(argument instanceof CacheLoaderArgument)) {
             throw new IllegalArgumentException("Unexpected argument type of " + argument.getClass().getName());
         }
 
-        final InternalTenantContext internalTenantContext = (InternalTenantContext) key;
+        final Long tenantRecordId = (Long) key;
+        final InternalTenantContext internalTenantContext = new InternalTenantContext(tenantRecordId);
         final CacheLoaderArgument cacheLoaderArgument = (CacheLoaderArgument) argument;
 
         if (cacheLoaderArgument.getArgs() == null || !(cacheLoaderArgument.getArgs()[0] instanceof LoaderCallback)) {
-            throw new IllegalArgumentException("Missing LoaderCallback from the arguments ");
+            throw new IllegalArgumentException("Missing LoaderCallback from the arguments");
         }
 
         final LoaderCallback callback = (LoaderCallback) cacheLoaderArgument.getArgs()[0];
@@ -72,14 +72,15 @@ public class TenantOverdueConfigCacheLoader extends BaseCacheLoader {
         try {
             logger.info("Loading overdue cache for tenant " + internalTenantContext.getTenantRecordId());
 
-            return callback.loadCatalog(overdueXML);
-        } catch (OverdueApiException e) {
+            return callback.loadOverdueConfig(overdueXML);
+        } catch (final OverdueApiException e) {
             throw new IllegalStateException(String.format("Failed to de-serialize overdue config for tenant %s : %s",
                                                           internalTenantContext.getTenantRecordId(), e.getMessage()), e);
         }
     }
 
     public interface LoaderCallback {
-        public Object loadCatalog(final String overdueXML) throws OverdueApiException;
+
+        public Object loadOverdueConfig(final String overdueConfigXML) throws OverdueApiException;
     }
 }