killbill-developers

added developers cache

12/17/2019 10:48:07 AM

Changes

account/pom.xml 50(+0 -50)

api/pom.xml 50(+0 -50)

blacklist 10(+0 -10)

catalog/pom.xml 46(+0 -46)

docker-compose.yml 10(+2 -8)

entitlement/pom.xml 50(+0 -50)

ignored 44(+0 -44)

invoice/pom.xml 50(+0 -50)

jaxrs/pom.xml 50(+0 -50)

junction/pom.xml 50(+0 -50)

overdue/pom.xml 46(+0 -46)

payment/pom.xml 50(+0 -50)

pom.xml 4(+2 -2)

tenant/pom.xml 50(+0 -50)

util/pom.xml 51(+5 -46)

whitelist 2(+0 -2)

Details

account/pom.xml 50(+0 -50)

diff --git a/account/pom.xml b/account/pom.xml
index f9f6da0..eec798b 100644
--- a/account/pom.xml
+++ b/account/pom.xml
@@ -191,54 +191,4 @@
             <scope>test</scope>
         </dependency>
     </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>aspectj-maven-plugin</artifactId>
-                <version>1.11</version>
-                <configuration>
-                    <showWeaveInfo>false</showWeaveInfo>
-                    <complianceLevel>1.8</complianceLevel>
-                    <source>1.8</source>
-                    <target>1.8</target>
-                    <Xlint>ignore</Xlint>
-                    <encoding>UTF-8</encoding>
-                    <verbose>false</verbose>
-                    <forceAjcCompile>true</forceAjcCompile>
-                    <sources/>
-                    <weaveDirectories>
-                        <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
-                    </weaveDirectories>
-                    <aspectLibraries>
-                        <aspectLibrary>
-                            <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
-                            <artifactId>ApplicationTracer</artifactId>
-                        </aspectLibrary>
-                    </aspectLibraries>
-                </configuration>
-                <executions>
-                    <execution>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>compile</goal>
-                            <goal>test-compile</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjrt</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjtools</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                </dependencies>
-            </plugin>
-       </plugins>
-    </build>
 </project>
diff --git a/account/src/main/java/org/killbill/billing/account/api/svcs/DefaultAccountInternalApi.java b/account/src/main/java/org/killbill/billing/account/api/svcs/DefaultAccountInternalApi.java
index e6d0a05..5a21243 100644
--- a/account/src/main/java/org/killbill/billing/account/api/svcs/DefaultAccountInternalApi.java
+++ b/account/src/main/java/org/killbill/billing/account/api/svcs/DefaultAccountInternalApi.java
@@ -53,6 +53,9 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableList;
 
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+import br.ufrgs.inf.prosoft.cache.*;
+
 public class DefaultAccountInternalApi extends DefaultAccountApiBase implements AccountInternalApi {
 
     private final ImmutableAccountInternalApi immutableAccountInternalApi;
@@ -98,8 +101,8 @@ public class DefaultAccountInternalApi extends DefaultAccountApiBase implements 
         final MutableAccountData mutableAccountData = currentAccount.toMutableAccountData();
         mutableAccountData.setBillCycleDayLocal(bcd);
         final AccountModelDao accountToUpdate = new AccountModelDao(currentAccount.getId(), mutableAccountData);
-        // bcdCacheController.remove(currentAccount.getId());
-        // bcdCacheController.putIfAbsent(currentAccount.getId(), new Integer(bcd));
+        CacheControllerDispatcher.bcdCacheController.invalidate(currentAccount.getId());
+        CacheControllerDispatcher.bcdCacheController.put(currentAccount.getId(), new Integer(bcd));
         accountDao.update(accountToUpdate, true, context);
     }
 
@@ -108,8 +111,11 @@ public class DefaultAccountInternalApi extends DefaultAccountApiBase implements 
         // final CacheLoaderArgument arg = createBCDCacheLoaderArgument(context);
         Preconditions.checkNotNull(context.getAccountRecordId(), "Context missing accountRecordId");
         final ImmutableAccountData account = immutableAccountInternalApi.getImmutableAccountDataByRecordId(context.getAccountRecordId(), context);
-        // final Integer result = bcdCacheController.get(account.getId(), arg);
-        final Integer result = accountDao.getAccountBCD(account.getId(), context);
+        Integer result = null;
+        try {
+            result = CacheControllerDispatcher.bcdCacheController.get(account.getId());
+        } catch (KeyNotFoundException ex) {
+        }
         return result != null ? result : DefaultMutableAccountData.DEFAULT_BILLING_CYCLE_DAY_LOCAL;
     }
 
diff --git a/account/src/main/java/org/killbill/billing/account/api/svcs/DefaultImmutableAccountInternalApi.java b/account/src/main/java/org/killbill/billing/account/api/svcs/DefaultImmutableAccountInternalApi.java
index 6adb006..4dded2e 100644
--- a/account/src/main/java/org/killbill/billing/account/api/svcs/DefaultImmutableAccountInternalApi.java
+++ b/account/src/main/java/org/killbill/billing/account/api/svcs/DefaultImmutableAccountInternalApi.java
@@ -48,12 +48,14 @@ import com.google.inject.Inject;
 
 import static org.killbill.billing.util.glue.IDBISetup.MAIN_RO_IDBI_NAMED;
 
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
 public class DefaultImmutableAccountInternalApi implements ImmutableAccountInternalApi {
 
     private final EntitySqlDaoTransactionalJdbiWrapper transactionalSqlDao;
     private final NonEntityDao nonEntityDao;
     // private final CacheController<Long, ImmutableAccountData> accountCacheController;
-    // private final CacheController<String, Long> recordIdCacheController;
+    // private final CacheController<String, Long> CacheControllerDispatcher.recordIdCacheController;
 
     @Inject
     public DefaultImmutableAccountInternalApi(final IDBI dbi,
@@ -66,21 +68,27 @@ public class DefaultImmutableAccountInternalApi implements ImmutableAccountInter
           nonEntityDao, null);
         this.nonEntityDao = nonEntityDao;
         // this.accountCacheController = cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_IMMUTABLE);
-        // this.recordIdCacheController = cacheControllerDispatcher.getCacheController(CacheType.RECORD_ID);
+        // this.CacheControllerDispatcher.recordIdCacheController = cacheControllerDispatcher.getCacheController(CacheType.RECORD_ID);
     }
 
     @Override
     public ImmutableAccountData getImmutableAccountDataById(final UUID accountId, final InternalTenantContext context) throws AccountApiException {
-        final Long recordId = nonEntityDao.retrieveRecordIdFromObject(accountId, ObjectType.ACCOUNT, null);
+        final Long recordId = nonEntityDao.retrieveRecordIdFromObject(accountId, ObjectType.ACCOUNT, CacheControllerDispatcher.recordIdCacheController);
         return getImmutableAccountDataByRecordId(recordId, context);
     }
 
     @Override
-    public ImmutableAccountData getImmutableAccountDataByRecordId(final Long recordId, final InternalTenantContext context) throws AccountApiException {
+    public ImmutableAccountData getImmutableAccountDataByRecordId(final Long recordId, final InternalTenantContext context) {//throws AccountApiException {
+return CacheControllerDispatcher.accountImmutableCacheController.computeIfAbsent(recordId, () -> {
         // final CacheLoaderArgument arg = createImmutableAccountCacheLoaderArgument(context);
         // return accountCacheController.get(recordId, arg);
+    try {
         final Account account = getAccountByRecordIdInternal(recordId, context);
         return account != null ? new DefaultImmutableAccountData(account) : null;
+    } catch (Exception ex){
+        throw new RuntimeException(ex);
+    }
+}, 20000);
     }
 
     // private CacheLoaderArgument createImmutableAccountCacheLoaderArgument(final InternalTenantContext context) {
diff --git a/account/src/main/java/org/killbill/billing/account/api/user/DefaultAccountApiBase.java b/account/src/main/java/org/killbill/billing/account/api/user/DefaultAccountApiBase.java
index 881d737..fd9c3f4 100644
--- a/account/src/main/java/org/killbill/billing/account/api/user/DefaultAccountApiBase.java
+++ b/account/src/main/java/org/killbill/billing/account/api/user/DefaultAccountApiBase.java
@@ -34,9 +34,12 @@ import org.killbill.billing.callcontext.InternalTenantContext;
 // import org.killbill.billing.util.cache.CacheControllerDispatcher;
 import org.killbill.billing.util.dao.NonEntityDao;
 
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
 public class DefaultAccountApiBase {
 
     private final AccountDao accountDao;
+
     // private final CacheController<Long, ImmutableAccountData> accountCacheController;
     // private final CacheController<String, Long> recordIdCacheController;
     private final NonEntityDao nonEntityDao;
@@ -50,12 +53,12 @@ public class DefaultAccountApiBase {
     }
 
     protected Account getAccountById(final UUID accountId, final InternalTenantContext context) throws AccountApiException {
-        final Long recordId = nonEntityDao.retrieveRecordIdFromObject(accountId, ObjectType.ACCOUNT, null);
+        final Long recordId = nonEntityDao.retrieveRecordIdFromObject(accountId, ObjectType.ACCOUNT, CacheControllerDispatcher.recordIdCacheController);
         final Account account = getAccountByRecordIdInternal(recordId, context);
         if (account == null) {
             throw new AccountApiException(ErrorCode.ACCOUNT_DOES_NOT_EXIST_FOR_ID, accountId);
         }
-        // accountCacheController.putIfAbsent(recordId, new DefaultImmutableAccountData(account));
+        CacheControllerDispatcher.accountCacheController.put(recordId, new DefaultImmutableAccountData(account));
         return account;
     }
 
@@ -65,8 +68,8 @@ public class DefaultAccountApiBase {
             throw new AccountApiException(ErrorCode.ACCOUNT_DOES_NOT_EXIST_FOR_KEY, key);
         }
         final Account account = new DefaultAccount(accountModelDao);
-        final Long recordId = nonEntityDao.retrieveRecordIdFromObject(account.getId(), ObjectType.ACCOUNT, null);
-        // accountCacheController.putIfAbsent(recordId, new DefaultImmutableAccountData(account));
+        final Long recordId = nonEntityDao.retrieveRecordIdFromObject(account.getId(), ObjectType.ACCOUNT, CacheControllerDispatcher.recordIdCacheController);
+        CacheControllerDispatcher.accountCacheController.put(recordId, new DefaultImmutableAccountData(account));
         return account;
     }
 
diff --git a/account/src/main/java/org/killbill/billing/account/dao/DefaultAccountDao.java b/account/src/main/java/org/killbill/billing/account/dao/DefaultAccountDao.java
index 1ab81f5..715f5fd 100644
--- a/account/src/main/java/org/killbill/billing/account/dao/DefaultAccountDao.java
+++ b/account/src/main/java/org/killbill/billing/account/dao/DefaultAccountDao.java
@@ -68,6 +68,8 @@ import com.google.inject.Inject;
 
 import static org.killbill.billing.util.glue.IDBISetup.MAIN_RO_IDBI_NAMED;
 
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
 public class DefaultAccountDao extends EntityDaoBase<AccountModelDao, Account, AccountApiException> implements AccountDao {
 
     private static final Logger log = LoggerFactory.getLogger(DefaultAccountDao.class);
@@ -105,7 +107,7 @@ public class DefaultAccountDao extends EntityDaoBase<AccountModelDao, Account, A
         // Populate the caches only after the transaction has been committed, in case of rollbacks
         // transactionalSqlDao.populateCaches(refreshedEntity);
         // Eagerly populate the account-immutable cache as well
-        // accountImmutableCacheController.putIfAbsent(refreshedEntity.getRecordId(), new DefaultImmutableAccountData(refreshedEntity));
+        CacheControllerDispatcher.accountImmutableCacheController.put(refreshedEntity.getRecordId(), new DefaultImmutableAccountData(refreshedEntity));
     }
 
     @Override

api/pom.xml 50(+0 -50)

diff --git a/api/pom.xml b/api/pom.xml
index a4164e5..af00cce 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -65,54 +65,4 @@
             <artifactId>config-magic</artifactId>
         </dependency>
     </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>aspectj-maven-plugin</artifactId>
-                <version>1.11</version>
-                <configuration>
-                    <showWeaveInfo>false</showWeaveInfo>
-                    <complianceLevel>1.8</complianceLevel>
-                    <source>1.8</source>
-                    <target>1.8</target>
-                    <Xlint>ignore</Xlint>
-                    <encoding>UTF-8</encoding>
-                    <verbose>false</verbose>
-                    <forceAjcCompile>true</forceAjcCompile>
-                    <sources/>
-                    <weaveDirectories>
-                        <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
-                    </weaveDirectories>
-                    <aspectLibraries>
-                        <aspectLibrary>
-                            <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
-                            <artifactId>ApplicationTracer</artifactId>
-                        </aspectLibrary>
-                    </aspectLibraries>
-                </configuration>
-                <executions>
-                    <execution>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>compile</goal>
-                            <goal>test-compile</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjrt</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjtools</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                </dependencies>
-            </plugin>
-       </plugins>
-    </build>
 </project>

catalog/pom.xml 46(+0 -46)

diff --git a/catalog/pom.xml b/catalog/pom.xml
index 335e287..2b1772c 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -188,52 +188,6 @@
     <build>
         <plugins>
             <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>aspectj-maven-plugin</artifactId>
-                <version>1.11</version>
-                <configuration>
-                    <showWeaveInfo>false</showWeaveInfo>
-                    <complianceLevel>1.8</complianceLevel>
-                    <source>1.8</source>
-                    <target>1.8</target>
-                    <Xlint>ignore</Xlint>
-                    <encoding>UTF-8</encoding>
-                    <verbose>false</verbose>
-                    <forceAjcCompile>true</forceAjcCompile>
-                    <sources/>
-                    <weaveDirectories>
-                        <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
-                    </weaveDirectories>
-                    <aspectLibraries>
-                        <aspectLibrary>
-                            <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
-                            <artifactId>ApplicationTracer</artifactId>
-                        </aspectLibrary>
-                    </aspectLibraries>
-                </configuration>
-                <executions>
-                    <execution>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>compile</goal>
-                            <goal>test-compile</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjrt</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjtools</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                </dependencies>
-            </plugin>
-            <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-shade-plugin</artifactId>
                 <executions>
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/caching/DefaultCatalogCache.java b/catalog/src/main/java/org/killbill/billing/catalog/caching/DefaultCatalogCache.java
index c895dcc..ba54bf7 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/caching/DefaultCatalogCache.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/caching/DefaultCatalogCache.java
@@ -52,10 +52,14 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
+import br.ufrgs.inf.prosoft.cache.*;
+
 public class DefaultCatalogCache implements CatalogCache {
 
     private final Logger logger = LoggerFactory.getLogger(DefaultCatalogCache.class);
 
+public static MultiCache<Long, DefaultVersionedCatalog> cacheController = new MultiCache<>("DefaultCatalogCache.cacheController");
+
     // private final CacheController<Long, DefaultVersionedCatalog> cacheController;
     private final VersionedCatalogLoader loader;
     // private final CacheLoaderArgument cacheLoaderArgumentWithTemplateFiltering;
@@ -116,8 +120,10 @@ public class DefaultCatalogCache implements CatalogCache {
         // 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 {
-            DefaultVersionedCatalog tenantCatalog =  null; // cacheController.get(tenantContext.getTenantRecordId(),
-                                                                        // filterTemplateCatalog ? cacheLoaderArgumentWithTemplateFiltering : cacheLoaderArgument);
+            DefaultVersionedCatalog tenantCatalog =  null;
+            try {
+                tenantCatalog =  cacheController.get(tenantContext.getTenantRecordId());
+            } catch (KeyNotFoundException ex) {}
             // It means we are using a default catalog in a multi-tenant deployment, that does not really match a real use case, but we want to support it
             // for test purpose.
             if (useDefaultCatalog && tenantCatalog == null) {
@@ -126,7 +132,7 @@ public class DefaultCatalogCache implements CatalogCache {
                     final StandaloneCatalogWithPriceOverride curWithOverride = new StandaloneCatalogWithPriceOverride(cur, priceOverride, tenantContext.getTenantRecordId(), internalCallContextFactory);
                     tenantCatalog.add(curWithOverride);
                 }
-                // cacheController.putIfAbsent(tenantContext.getTenantRecordId(), tenantCatalog);
+                cacheController.put(tenantContext.getTenantRecordId(), tenantCatalog);
             }
 
             if (tenantCatalog != null) {
@@ -141,9 +147,9 @@ public class DefaultCatalogCache implements CatalogCache {
 
     @Override
     public void clearCatalog(final InternalTenantContext tenantContext) {
-        // if (!InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID.equals(tenantContext.getTenantRecordId())) {
-            // cacheController.remove(tenantContext.getTenantRecordId());
-        // }
+        if (!InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID.equals(tenantContext.getTenantRecordId())) {
+            cacheController.invalidate(tenantContext.getTenantRecordId());
+        }
     }
 
     private DefaultVersionedCatalog getCatalogFromPlugins(final InternalTenantContext internalTenantContext) throws CatalogApiException {
@@ -163,14 +169,17 @@ public class DefaultCatalogCache implements CatalogCache {
             // A null latestCatalogUpdatedDate bypasses caching, by fetching full catalog from plugin below (compatibility mode with 0.18.x or non optimized plugin api mode)
             // final boolean cacheable = latestCatalogUpdatedDate != null;
             // if (cacheable) {
-            //     final DefaultVersionedCatalog tenantCatalog = cacheController.get(internalTenantContext.getTenantRecordId(), cacheLoaderArgument);
-            //     if (tenantCatalog != null) {
-            //         initializeCatalog(tenantCatalog);
-            //         if (tenantCatalog.getEffectiveDate().compareTo(latestCatalogUpdatedDate.toDate()) == 0) {
+                DefaultVersionedCatalog tenantCatalog = null;
+                try {
+                    tenantCatalog = cacheController.get(internalTenantContext.getTenantRecordId());
+                } catch (KeyNotFoundException ex){}
+                if (tenantCatalog != null) {
+                    initializeCatalog(tenantCatalog);
+                    if (tenantCatalog.getEffectiveDate().compareTo(latestCatalogUpdatedDate.toDate()) == 0) {
             //             // Current cached version matches the one from the plugin
-            //             return tenantCatalog;
-            //         }
-            //     }
+                        return tenantCatalog;
+                    }
+                }
             // }
 
             final VersionedPluginCatalog pluginCatalog = plugin.getVersionedPluginCatalog(ImmutableList.<PluginProperty>of(), tenantContext);
@@ -184,9 +193,9 @@ public class DefaultCatalogCache implements CatalogCache {
                 final DefaultVersionedCatalog resolvedPluginCatalog = versionedCatalogMapper.toVersionedCatalog(pluginCatalog, internalTenantContext);
 
                 // Always clear the cache for safety
-                // cacheController.remove(internalTenantContext.getTenantRecordId());
+                cacheController.invalidate(internalTenantContext.getTenantRecordId());
                 // if (cacheable) {
-                //     cacheController.putIfAbsent(internalTenantContext.getTenantRecordId(), resolvedPluginCatalog);
+                    cacheController.put(internalTenantContext.getTenantRecordId(), resolvedPluginCatalog);
                 // }
 
                 return resolvedPluginCatalog;
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/caching/DefaultOverriddenPlanCache.java b/catalog/src/main/java/org/killbill/billing/catalog/caching/DefaultOverriddenPlanCache.java
index f75deb6..9888f3c 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/caching/DefaultOverriddenPlanCache.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/caching/DefaultOverriddenPlanCache.java
@@ -56,11 +56,15 @@ import org.killbill.billing.catalog.override.DefaultPriceOverride;
 // import org.killbill.billing.util.cache.CacheLoaderArgument;
 // import org.killbill.billing.util.cache.OverriddenPlanCacheLoader.LoaderCallback;
 
+import br.ufrgs.inf.prosoft.cache.*;
+
 import com.google.common.base.Predicate;
 import com.google.common.collect.Iterables;
 
 public class DefaultOverriddenPlanCache implements OverriddenPlanCache {
 
+public static MultiCache<String, Plan> cacheController = new MultiCache<>("DefaultOverriddenPlanCache.cacheController");
+
     // private final CacheController<String, Plan> cacheController;
     // private final LoaderCallback loaderCallback;
     private final CatalogOverrideDao overrideDao;
@@ -86,6 +90,7 @@ public class DefaultOverriddenPlanCache implements OverriddenPlanCache {
 
         // final CacheLoaderArgument argument = new CacheLoaderArgument(irrelevant, args, context);
         // final DefaultPlan defaultPlan = (DefaultPlan) cacheController.get(planName, argument);
+return (DefaultPlan) cacheController.computeIfAbsent(planName, () -> {
         DefaultPlan defaultPlan = null;
         try {
             defaultPlan = (DefaultPlan) loadOverriddenPlan(planName, (StandaloneCatalog) catalog, context);
@@ -93,11 +98,12 @@ public class DefaultOverriddenPlanCache implements OverriddenPlanCache {
         } catch(CatalogApiException ex){
         }
         return defaultPlan;
+}, 20000);
     }
 
     @Override
     public void addDryRunPlan(final String planName, final Plan plan) {
-        // cacheController.putIfAbsent(planName, plan);
+        cacheController.put(planName, plan);
     }
 
     private DefaultPlan loadOverriddenPlan(final String planName, final StandaloneCatalog catalog, final InternalTenantContext context) throws CatalogApiException {

docker-compose.yml 10(+2 -8)

diff --git a/docker-compose.yml b/docker-compose.yml
index cba3982..8ed42e3 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -17,14 +17,8 @@ services:
       - KILLBILL_DAO_USER=root
       - KILLBILL_DAO_PASSWORD=killbill
       - JAVA_OPTS=${JAVA_OPTS:-"-Xms4096m -Xmx6124m"}
-      - TRACER_ENABLE=${TRACER_ENABLE:-true}
-      - TRACER_MINIMUM_EXECUTION_TIME=${TRACER_MINIMUM_EXECUTION_TIME:-1}
-      - TRACER_SERIALISE_INTERNALS=false
-      - TRACER_VERBOSE=true
-      - TRACER_TRACES=/caching-approaches-comparison/applications/traces/killbill
-      - TRACER_IGNORED_PACKAGES=/caching-approaches-comparison/applications/uncached/killbill/ignored
-      - TRACER_WHITELIST=/caching-approaches-comparison/applications/uncached/killbill/whitelist
-      - TRACER_LOG=/caching-approaches-comparison/applications/output/killbill-tracer.log
+      - CACHE_EVENTS=${CACHE_EVENTS:-/caching-approaches-comparison/applications/output/killbill-developers-cache}
+      - CACHE_REGISTER_SIZE=false
     volumes:
       - application:/application
       - /root/.m2:/root/.m2

entitlement/pom.xml 50(+0 -50)

diff --git a/entitlement/pom.xml b/entitlement/pom.xml
index bc36b0d..fce0269 100644
--- a/entitlement/pom.xml
+++ b/entitlement/pom.xml
@@ -214,54 +214,4 @@
             <scope>test</scope>
         </dependency>
     </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>aspectj-maven-plugin</artifactId>
-                <version>1.11</version>
-                <configuration>
-                    <showWeaveInfo>false</showWeaveInfo>
-                    <complianceLevel>1.8</complianceLevel>
-                    <source>1.8</source>
-                    <target>1.8</target>
-                    <Xlint>ignore</Xlint>
-                    <encoding>UTF-8</encoding>
-                    <verbose>false</verbose>
-                    <forceAjcCompile>true</forceAjcCompile>
-                    <sources/>
-                    <weaveDirectories>
-                        <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
-                    </weaveDirectories>
-                    <aspectLibraries>
-                        <aspectLibrary>
-                            <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
-                            <artifactId>ApplicationTracer</artifactId>
-                        </aspectLibrary>
-                    </aspectLibraries>
-                </configuration>
-                <executions>
-                    <execution>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>compile</goal>
-                            <goal>test-compile</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjrt</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjtools</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                </dependencies>
-            </plugin>
-       </plugins>
-    </build>
 </project>
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/dao/DefaultBlockingStateDao.java b/entitlement/src/main/java/org/killbill/billing/entitlement/dao/DefaultBlockingStateDao.java
index bb26552..9eb3648 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/dao/DefaultBlockingStateDao.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/dao/DefaultBlockingStateDao.java
@@ -78,6 +78,8 @@ import com.google.common.collect.Ordering;
 
 import static org.killbill.billing.util.glue.IDBISetup.MAIN_RO_IDBI_NAMED;
 
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
 public class DefaultBlockingStateDao extends EntityDaoBase<BlockingStateModelDao, BlockingState, EntitlementApiException> implements BlockingStateDao {
 
     private static final Logger log = LoggerFactory.getLogger(DefaultBlockingStateDao.class);
@@ -279,13 +281,13 @@ public class DefaultBlockingStateDao extends EntityDaoBase<BlockingStateModelDao
         final List<BlockingState> bundleBlockingStates;
         final List<BlockingState> subscriptionBlockingStates;
         if (type == BlockingStateType.SUBSCRIPTION) {
-            final UUID accountId = nonEntityDao.retrieveIdFromObjectInTransaction(context.getAccountRecordId(), ObjectType.ACCOUNT, null, handle);
+            final UUID accountId = nonEntityDao.retrieveIdFromObjectInTransaction(context.getAccountRecordId(), ObjectType.ACCOUNT, CacheControllerDispatcher.objectIdCacheController, handle);
             final List<BlockingState> allBlockingStatesForAccount = getBlockingAllUpToForAccountRecordId(sqlDao, upToDate, context);
             accountBlockingStates = filterBlockingStates(allBlockingStatesForAccount, accountId, BlockingStateType.ACCOUNT);
             bundleBlockingStates = filterBlockingStates(allBlockingStatesForAccount, bundleId, BlockingStateType.SUBSCRIPTION_BUNDLE);
             subscriptionBlockingStates = filterBlockingStates(allBlockingStatesForAccount, blockableId, BlockingStateType.SUBSCRIPTION);
         } else if (type == BlockingStateType.SUBSCRIPTION_BUNDLE) {
-            final UUID accountId = nonEntityDao.retrieveIdFromObjectInTransaction(context.getAccountRecordId(), ObjectType.ACCOUNT, null, handle);
+            final UUID accountId = nonEntityDao.retrieveIdFromObjectInTransaction(context.getAccountRecordId(), ObjectType.ACCOUNT, CacheControllerDispatcher.objectIdCacheController, handle);
             final List<BlockingState> allBlockingStatesForAccount = getBlockingAllUpToForAccountRecordId(sqlDao, upToDate, context);
             accountBlockingStates = filterBlockingStates(allBlockingStatesForAccount, accountId, BlockingStateType.ACCOUNT);
             bundleBlockingStates = filterBlockingStates(allBlockingStatesForAccount, blockableId, BlockingStateType.SUBSCRIPTION_BUNDLE);

invoice/pom.xml 50(+0 -50)

diff --git a/invoice/pom.xml b/invoice/pom.xml
index 37e9f4d..45a3262 100644
--- a/invoice/pom.xml
+++ b/invoice/pom.xml
@@ -232,54 +232,4 @@
             <scope>test</scope>
         </dependency>
     </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>aspectj-maven-plugin</artifactId>
-                <version>1.11</version>
-                <configuration>
-                    <showWeaveInfo>false</showWeaveInfo>
-                    <complianceLevel>1.8</complianceLevel>
-                    <source>1.8</source>
-                    <target>1.8</target>
-                    <Xlint>ignore</Xlint>
-                    <encoding>UTF-8</encoding>
-                    <verbose>false</verbose>
-                    <forceAjcCompile>true</forceAjcCompile>
-                    <sources/>
-                    <weaveDirectories>
-                        <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
-                    </weaveDirectories>
-                    <aspectLibraries>
-                        <aspectLibrary>
-                            <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
-                            <artifactId>ApplicationTracer</artifactId>
-                        </aspectLibrary>
-                    </aspectLibraries>
-                </configuration>
-                <executions>
-                    <execution>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>compile</goal>
-                            <goal>test-compile</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjrt</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjtools</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                </dependencies>
-            </plugin>
-       </plugins>
-    </build>
 </project>

jaxrs/pom.xml 50(+0 -50)

diff --git a/jaxrs/pom.xml b/jaxrs/pom.xml
index e3bc326..4a269ca 100644
--- a/jaxrs/pom.xml
+++ b/jaxrs/pom.xml
@@ -201,54 +201,4 @@
             <scope>test</scope>
         </dependency>
     </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>aspectj-maven-plugin</artifactId>
-                <version>1.11</version>
-                <configuration>
-                    <showWeaveInfo>false</showWeaveInfo>
-                    <complianceLevel>1.8</complianceLevel>
-                    <source>1.8</source>
-                    <target>1.8</target>
-                    <Xlint>ignore</Xlint>
-                    <encoding>UTF-8</encoding>
-                    <verbose>false</verbose>
-                    <forceAjcCompile>true</forceAjcCompile>
-                    <sources/>
-                    <weaveDirectories>
-                        <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
-                    </weaveDirectories>
-                    <aspectLibraries>
-                        <aspectLibrary>
-                            <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
-                            <artifactId>ApplicationTracer</artifactId>
-                        </aspectLibrary>
-                    </aspectLibraries>
-                </configuration>
-                <executions>
-                    <execution>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>compile</goal>
-                            <goal>test-compile</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjrt</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjtools</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                </dependencies>
-            </plugin>
-       </plugins>
-    </build>
 </project>
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 72d84a6..db60e6d 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
@@ -104,6 +104,8 @@ import io.swagger.annotations.ApiResponses;
 import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
 
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
 @Singleton
 @Path(JaxrsResource.ADMIN_PATH)
 @Api(value = JaxrsResource.ADMIN_PATH, description = "Admin operations (will require special privileges)", tags="Admin")
@@ -361,15 +363,15 @@ public class AdminResource extends JaxRsResourceBase {
 
         // clear account-record-id cache by accountId (note: String!)
         // final CacheController<String, Long> accountRecordIdCacheController = cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_RECORD_ID);
-        // accountRecordIdCacheController.remove(accountId.toString());
+        CacheControllerDispatcher.accountRecordIdCacheController.invalidate(accountId.toString());
 
         // clear account-immutable cache by account record id
         // final CacheController<Long, ImmutableAccountData> accountImmutableCacheController = cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_IMMUTABLE);
-        // accountImmutableCacheController.remove(accountRecordId);
+        CacheControllerDispatcher.accountImmutableCacheController.invalidate(accountRecordId);
 
         // clear account-bcd cache by accountId (note: UUID!)
         // final CacheController<UUID, Integer> accountBCDCacheController = cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_BCD);
-        // accountBCDCacheController.remove(accountId);
+        CacheControllerDispatcher.bcdCacheController.invalidate(accountId);
 
         return Response.status(Status.NO_CONTENT).build();
     }
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java
index 4ab1e3d..2d442dc 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java
@@ -117,6 +117,8 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
+import br.ufrgs.inf.prosoft.cache.*;
+
 public abstract class JaxRsResourceBase implements JaxrsResource {
 
     static final Logger log = LoggerFactory.getLogger(JaxRsResourceBase.class);
@@ -201,14 +203,18 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
     protected Response createTagResponse(final UUID accountId, final List<Tag> tags, final AuditMode auditMode, final TenantContext context) throws TagDefinitionApiException {
         final AccountAuditLogsForObjectType tagsAuditLogs = auditUserApi.getAccountAuditLogs(accountId, ObjectType.TAG, auditMode.getLevel(), context);
 
+MultiCache<UUID, TagDefinition> createTagResponse = new MultiCache<>("JaxRsResourceBase.createTagResponse");
+
         // final Map<UUID, TagDefinition> tagDefinitionsCache = new HashMap<UUID, TagDefinition>();
         final Collection<TagJson> result = new LinkedList<TagJson>();
         for (final Tag tag : tags) {
-            // if (tagDefinitionsCache.get(tag.getTagDefinitionId()) == null) {
-                // tagDefinitionsCache.put(tag.getTagDefinitionId(), tagUserApi.getTagDefinition(tag.getTagDefinitionId(), context));
-            // }
-            // final TagDefinition tagDefinition = tagDefinitionsCache.get(tag.getTagDefinitionId());
-            final TagDefinition tagDefinition = tagUserApi.getTagDefinition(tag.getTagDefinitionId(), context);
+            if (!createTagResponse.containsKey(tag.getTagDefinitionId())) {
+                createTagResponse.put(tag.getTagDefinitionId(), tagUserApi.getTagDefinition(tag.getTagDefinitionId(), context));
+            }
+            TagDefinition tagDefinition = null;
+            try {
+                tagDefinition = createTagResponse.get(tag.getTagDefinitionId());
+            } catch (KeyNotFoundException ex){}
 
             final List<AuditLog> auditLogs = tagsAuditLogs.getAuditLogs(tag.getId());
             result.add(new TagJson(tag, tagDefinition, auditLogs));

junction/pom.xml 50(+0 -50)

diff --git a/junction/pom.xml b/junction/pom.xml
index afeb9d9..134d3d7 100644
--- a/junction/pom.xml
+++ b/junction/pom.xml
@@ -206,54 +206,4 @@
             <scope>test</scope>
         </dependency>
     </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>aspectj-maven-plugin</artifactId>
-                <version>1.11</version>
-                <configuration>
-                    <showWeaveInfo>false</showWeaveInfo>
-                    <complianceLevel>1.8</complianceLevel>
-                    <source>1.8</source>
-                    <target>1.8</target>
-                    <Xlint>ignore</Xlint>
-                    <encoding>UTF-8</encoding>
-                    <verbose>false</verbose>
-                    <forceAjcCompile>true</forceAjcCompile>
-                    <sources/>
-                    <weaveDirectories>
-                        <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
-                    </weaveDirectories>
-                    <aspectLibraries>
-                        <aspectLibrary>
-                            <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
-                            <artifactId>ApplicationTracer</artifactId>
-                        </aspectLibrary>
-                    </aspectLibraries>
-                </configuration>
-                <executions>
-                    <execution>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>compile</goal>
-                            <goal>test-compile</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjrt</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjtools</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                </dependencies>
-            </plugin>
-       </plugins>
-    </build>
 </project>

overdue/pom.xml 46(+0 -46)

diff --git a/overdue/pom.xml b/overdue/pom.xml
index d343e45..445b503 100644
--- a/overdue/pom.xml
+++ b/overdue/pom.xml
@@ -206,52 +206,6 @@
     <build>
         <plugins>
             <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>aspectj-maven-plugin</artifactId>
-                <version>1.11</version>
-                <configuration>
-                    <showWeaveInfo>false</showWeaveInfo>
-                    <complianceLevel>1.8</complianceLevel>
-                    <source>1.8</source>
-                    <target>1.8</target>
-                    <Xlint>ignore</Xlint>
-                    <encoding>UTF-8</encoding>
-                    <verbose>false</verbose>
-                    <forceAjcCompile>true</forceAjcCompile>
-                    <sources/>
-                    <weaveDirectories>
-                        <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
-                    </weaveDirectories>
-                    <aspectLibraries>
-                        <aspectLibrary>
-                            <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
-                            <artifactId>ApplicationTracer</artifactId>
-                        </aspectLibrary>
-                    </aspectLibraries>
-                </configuration>
-                <executions>
-                    <execution>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>compile</goal>
-                            <goal>test-compile</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjrt</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjtools</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                </dependencies>
-            </plugin>
-            <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-shade-plugin</artifactId>
                 <executions>
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/caching/DefaultOverdueConfigCache.java b/overdue/src/main/java/org/killbill/billing/overdue/caching/DefaultOverdueConfigCache.java
index 8da8069..f4d4b7d 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/caching/DefaultOverdueConfigCache.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/caching/DefaultOverdueConfigCache.java
@@ -42,10 +42,14 @@ import org.slf4j.LoggerFactory;
 
 import org.killbill.billing.tenant.api.TenantInternalApi;
 
+import br.ufrgs.inf.prosoft.cache.*;
+
 public class DefaultOverdueConfigCache implements OverdueConfigCache {
 
     private static final Logger log = LoggerFactory.getLogger(DefaultOverdueConfigCache.class);
 
+public static MultiCache<Long, OverdueConfig> cacheController = new MultiCache<>("DefaultOverdueConfig.cacheController");
+
     // private final CacheController<Long, OverdueConfig> cacheController;
     // private final CacheLoaderArgument cacheLoaderArgument;
 
@@ -103,19 +107,21 @@ public class DefaultOverdueConfigCache implements OverdueConfigCache {
         // 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;// = cacheController.get(tenantContext.getTenantRecordId(), cacheLoaderArgument);
-
-            final String overdueXML = tenantApi.getTenantOverdueConfig(tenantContext);
-            if (overdueXML == null) {
-                throw new OverdueApiException(ErrorCode.OVERDUE_INVALID_FOR_TENANT, "Problem encountered loading overdue config ");
-            }
-
-            final InputStream overdueConfigStream = new ByteArrayInputStream(overdueXML.getBytes());
-            try {
-                overdueConfig =  XMLLoader.getObjectFromStream(overdueConfigStream, DefaultOverdueConfig.class);
-            } catch (final Exception e) {
-                throw new OverdueApiException(ErrorCode.OVERDUE_INVALID_FOR_TENANT, "Problem encountered loading overdue config ", e);
-            }
+            final OverdueConfig overdueConfig = cacheController.computeIfAbsent(tenantContext.getTenantRecordId(), () -> {
+                final String overdueXML = tenantApi.getTenantOverdueConfig(tenantContext);
+                if (overdueXML == null) {
+                    // throw new OverdueApiException(ErrorCode.OVERDUE_INVALID_FOR_TENANT, "Problem encountered loading overdue config ");
+                    throw new RuntimeException();
+                }
+
+                final InputStream overdueConfigStream = new ByteArrayInputStream(overdueXML.getBytes());
+                try {
+                    return  XMLLoader.getObjectFromStream(overdueConfigStream, DefaultOverdueConfig.class);
+                } catch (final Exception e) {
+                    // throw new OverdueApiException(ErrorCode.OVERDUE_INVALID_FOR_TENANT, "Problem encountered loading overdue config ", e);
+                    throw new RuntimeException(e);
+                }
+            });
 
             return (overdueConfig != null) ? overdueConfig : defaultOverdueConfig;
         } catch (final IllegalStateException e) {
@@ -125,9 +131,9 @@ public class DefaultOverdueConfigCache implements OverdueConfigCache {
 
     @Override
     public void clearOverdueConfig(final InternalTenantContext tenantContext) {
-        // if (!InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID.equals(tenantContext.getTenantRecordId())) {
-        //     cacheController.remove(tenantContext.getTenantRecordId());
-        // }
+        if (!InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID.equals(tenantContext.getTenantRecordId())) {
+            cacheController.invalidate(tenantContext.getTenantRecordId());
+        }
     }
 
     // private CacheLoaderArgument initializeCacheLoaderArgument() {
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/listener/OverdueListener.java b/overdue/src/main/java/org/killbill/billing/overdue/listener/OverdueListener.java
index 35e5f2e..5ac4a63 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/listener/OverdueListener.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/listener/OverdueListener.java
@@ -61,6 +61,9 @@ import com.google.common.eventbus.AllowConcurrentEvents;
 import com.google.common.eventbus.Subscribe;
 import com.google.inject.Inject;
 
+import org.killbill.billing.util.cache.*;
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
 public class OverdueListener {
 
     private static final Logger log = LoggerFactory.getLogger(OverdueListener.class);
@@ -97,7 +100,7 @@ public class OverdueListener {
             final InternalCallContext internalCallContext = createCallContext(event.getUserToken(), event.getSearchKey1(), event.getSearchKey2());
             insertBusEventIntoNotificationQueue(event.getObjectId(), OverdueAsyncBusNotificationAction.CLEAR, internalCallContext);
         } else if (event.getTagDefinition().getName().equals(ControlTagType.WRITTEN_OFF.toString()) && event.getObjectType() == ObjectType.INVOICE) {
-            final UUID accountId = nonEntityDao.retrieveIdFromObject(event.getSearchKey1(), ObjectType.ACCOUNT, null);
+            final UUID accountId = nonEntityDao.retrieveIdFromObject(event.getSearchKey1(), ObjectType.ACCOUNT, CacheControllerDispatcher.objectIdCacheController);
             insertBusEventIntoNotificationQueue(accountId, event);
         }
     }
@@ -108,7 +111,7 @@ public class OverdueListener {
         if (event.getTagDefinition().getName().equals(ControlTagType.OVERDUE_ENFORCEMENT_OFF.toString()) && event.getObjectType() == ObjectType.ACCOUNT) {
             insertBusEventIntoNotificationQueue(event.getObjectId(), event);
         } else if (event.getTagDefinition().getName().equals(ControlTagType.WRITTEN_OFF.toString()) && event.getObjectType() == ObjectType.INVOICE) {
-            final UUID accountId = nonEntityDao.retrieveIdFromObject(event.getSearchKey1(), ObjectType.ACCOUNT, null);
+            final UUID accountId = nonEntityDao.retrieveIdFromObject(event.getSearchKey1(), ObjectType.ACCOUNT, CacheControllerDispatcher.objectIdCacheController);
             insertBusEventIntoNotificationQueue(accountId, event);
         }
     }

payment/pom.xml 50(+0 -50)

diff --git a/payment/pom.xml b/payment/pom.xml
index 4e8f48d..1277f2c 100644
--- a/payment/pom.xml
+++ b/payment/pom.xml
@@ -249,54 +249,4 @@
             <scope>test</scope>
         </dependency>
     </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>aspectj-maven-plugin</artifactId>
-                <version>1.11</version>
-                <configuration>
-                    <showWeaveInfo>false</showWeaveInfo>
-                    <complianceLevel>1.8</complianceLevel>
-                    <source>1.8</source>
-                    <target>1.8</target>
-                    <Xlint>ignore</Xlint>
-                    <encoding>UTF-8</encoding>
-                    <verbose>false</verbose>
-                    <forceAjcCompile>true</forceAjcCompile>
-                    <sources/>
-                    <weaveDirectories>
-                        <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
-                    </weaveDirectories>
-                    <aspectLibraries>
-                        <aspectLibrary>
-                            <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
-                            <artifactId>ApplicationTracer</artifactId>
-                        </aspectLibrary>
-                    </aspectLibraries>
-                </configuration>
-                <executions>
-                    <execution>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>compile</goal>
-                            <goal>test-compile</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjrt</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjtools</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                </dependencies>
-            </plugin>
-       </plugins>
-    </build>
 </project>
diff --git a/payment/src/main/java/org/killbill/billing/payment/caching/DefaultStateMachineConfigCache.java b/payment/src/main/java/org/killbill/billing/payment/caching/DefaultStateMachineConfigCache.java
index 12e47c9..0215d08 100644
--- a/payment/src/main/java/org/killbill/billing/payment/caching/DefaultStateMachineConfigCache.java
+++ b/payment/src/main/java/org/killbill/billing/payment/caching/DefaultStateMachineConfigCache.java
@@ -35,7 +35,7 @@ import org.killbill.billing.tenant.api.TenantInternalApi;
 import org.killbill.billing.tenant.api.TenantKV.TenantKey;
 // 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.cache.CacheControllerDispatcher;
 // import org.killbill.billing.util.cache.CacheLoaderArgument;
 // import org.killbill.billing.util.cache.TenantStateMachineConfigCacheLoader.LoaderCallback;
 import org.killbill.billing.util.callcontext.InternalCallContextFactory;
@@ -45,10 +45,14 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.io.Resources;
 
+import br.ufrgs.inf.prosoft.cache.*;
+
 public class DefaultStateMachineConfigCache implements StateMachineConfigCache {
 
     private static final Logger logger = LoggerFactory.getLogger(DefaultStateMachineConfigCache.class);
 
+public static MultiCache<String, StateMachineConfig> cacheController = new MultiCache<>("DefaultStateMachineConfigCache.cacheController");
+
     // private final CacheController<String, StateMachineConfig> cacheController;
     // private final LoaderCallback loaderCallback;
 
@@ -97,62 +101,65 @@ public class DefaultStateMachineConfigCache implements StateMachineConfigCache {
             return defaultPaymentStateMachineConfig;
         }
 
-        // final String pluginConfigKey = getCacheKeyName(pluginName, tenantContext);
+        final String pluginConfigKey = getCacheKeyName(pluginName, tenantContext);
         // final CacheLoaderArgument cacheLoaderArgument = createCacheLoaderArgument(pluginName);
 
-        try {
-            StateMachineConfig pluginPaymentStateMachineConfig = null;// = cacheController.get(pluginConfigKey, cacheLoaderArgument);
-
-final String tenantRecordId = String.valueOf(tenantContext.getTenantRecordId());
 
-final InternalTenantContext internalTenantContext = new InternalTenantContext(Long.valueOf(tenantRecordId));
-final String stateMachineConfigXML = tenantApi.getPluginPaymentStateMachineConfig(pluginName, internalTenantContext);
-try {
-if (stateMachineConfigXML == null) {
-    throw new Exception();
-}
+return cacheController.computeIfAbsent(pluginConfigKey, () -> {
+        try {
+            final String tenantRecordId = String.valueOf(tenantContext.getTenantRecordId());
 
-    logger.info("Loading config state machine cache for pluginName='{}', tenantRecordId='{}'", pluginName, tenantContext.getTenantRecordId());
-    final InputStream stream = new ByteArrayInputStream(stateMachineConfigXML.getBytes());
-    pluginPaymentStateMachineConfig = XMLLoader.getObjectFromStream(stream, DefaultStateMachineConfig.class);
-// } catch (final PaymentApiException e) {
-//     throw new IllegalStateException(String.format("Failed to de-serialize state machine config for tenantRecordId='%s'", internalTenantContext.getTenantRecordId()), e);
-// }
-                } catch (final Exception e) {
-                    // TODO 0.17 proper error code
-                    throw new PaymentApiException(e, ErrorCode.PAYMENT_INTERNAL_ERROR, "Invalid payment state machine config");
-                }
+            final InternalTenantContext internalTenantContext = new InternalTenantContext(Long.valueOf(tenantRecordId));
+            final String stateMachineConfigXML = tenantApi.getPluginPaymentStateMachineConfig(pluginName, internalTenantContext);
+            
+            if (stateMachineConfigXML == null) {
+                throw new RuntimeException();
+            }
+            StateMachineConfig pluginPaymentStateMachineConfig = null;
+            try {
 
+                logger.info("Loading config state machine cache for pluginName='{}', tenantRecordId='{}'", pluginName, tenantContext.getTenantRecordId());
+                final InputStream stream = new ByteArrayInputStream(stateMachineConfigXML.getBytes());
+                pluginPaymentStateMachineConfig = XMLLoader.getObjectFromStream(stream, DefaultStateMachineConfig.class);
+            // } catch (final PaymentApiException e) {
+            //     throw new IllegalStateException(String.format("Failed to de-serialize state machine config for tenantRecordId='%s'", internalTenantContext.getTenantRecordId()), e);
+            // }
+                    } catch (final Exception e) {
+                        // TODO 0.17 proper error code
+                        // throw new PaymentApiException(e, ErrorCode.PAYMENT_INTERNAL_ERROR, "Invalid payment state machine config");
+                        throw new RuntimeException(e);
+                    }
 
             // It means we are using the default state machine config in a multi-tenant deployment
             if (pluginPaymentStateMachineConfig == null) {
                 pluginPaymentStateMachineConfig = defaultPaymentStateMachineConfig;
-                // cacheController.putIfAbsent(pluginConfigKey, pluginPaymentStateMachineConfig);
             }
 
             ((DefaultStateMachineConfig)pluginPaymentStateMachineConfig).initialize(defaultPaymentStateMachineConfig);
             return pluginPaymentStateMachineConfig;
         } catch (final IllegalStateException e) {
             // TODO 0.17 proper error code
-            throw new PaymentApiException(e, ErrorCode.PAYMENT_INTERNAL_ERROR, "Invalid payment state machine");
+            // throw new PaymentApiException(e, ErrorCode.PAYMENT_INTERNAL_ERROR, "Invalid payment state machine");
+            throw new RuntimeException(e);
         }
+});
     }
 
     // See also DefaultTenantUserApi - we use the same conventions as the main XML cache (so we can re-use the invalidation code)
-    // private String getCacheKeyName(final String pluginName, final InternalTenantContext internalContext) {
-    //     final StringBuilder tenantKey = new StringBuilder(TenantKey.PLUGIN_PAYMENT_STATE_MACHINE_.toString());
-    //     tenantKey.append(pluginName);
-    //     tenantKey.append(CacheControllerDispatcher.CACHE_KEY_SEPARATOR);
-    //     tenantKey.append(internalContext.getTenantRecordId());
-    //     return tenantKey.toString();
-    // }
+    private String getCacheKeyName(final String pluginName, final InternalTenantContext internalContext) {
+        final StringBuilder tenantKey = new StringBuilder(TenantKey.PLUGIN_PAYMENT_STATE_MACHINE_.toString());
+        tenantKey.append(pluginName);
+        tenantKey.append(CacheControllerDispatcher.CACHE_KEY_SEPARATOR);
+        tenantKey.append(internalContext.getTenantRecordId());
+        return tenantKey.toString();
+    }
 
     @Override
     public void clearPaymentStateMachineConfig(final String pluginName, final InternalTenantContext tenantContext) {
-        // if (!InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID.equals(tenantContext.getTenantRecordId()) && cacheController != null) {
-        //     final String key = getCacheKeyName(pluginName, tenantContext);
-        //     cacheController.remove(key);
-        // }
+        if (!InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID.equals(tenantContext.getTenantRecordId()) && cacheController != null) {
+            final String key = getCacheKeyName(pluginName, tenantContext);
+            cacheController.invalidate(key);
+        }
     }
 
     // private CacheLoaderArgument createCacheLoaderArgument(final String pluginName) {

pom.xml 4(+2 -2)

diff --git a/pom.xml b/pom.xml
index 036d73e..7068082 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,8 +49,8 @@
     </modules>
     <dependencies>
         <dependency>
-            <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
-            <artifactId>ApplicationTracer</artifactId>
+            <groupId>br.ufrgs.inf.prosoft.cache</groupId>
+            <artifactId>Cache</artifactId>
             <version>1.0</version>
         </dependency>
     </dependencies>
diff --git a/profiles/killbill/pom.xml b/profiles/killbill/pom.xml
index e58a90c..5ac48b3 100644
--- a/profiles/killbill/pom.xml
+++ b/profiles/killbill/pom.xml
@@ -471,52 +471,6 @@
         </resources>
         <plugins>
             <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>aspectj-maven-plugin</artifactId>
-                <version>1.11</version>
-                <configuration>
-                    <showWeaveInfo>false</showWeaveInfo>
-                    <complianceLevel>1.8</complianceLevel>
-                    <source>1.8</source>
-                    <target>1.8</target>
-                    <Xlint>ignore</Xlint>
-                    <encoding>UTF-8</encoding>
-                    <verbose>false</verbose>
-                    <forceAjcCompile>true</forceAjcCompile>
-                    <sources/>
-                    <weaveDirectories>
-                        <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
-                    </weaveDirectories>
-                    <aspectLibraries>
-                        <aspectLibrary>
-                            <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
-                            <artifactId>ApplicationTracer</artifactId>
-                        </aspectLibrary>
-                    </aspectLibraries>
-                </configuration>
-                <executions>
-                    <execution>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>compile</goal>
-                            <goal>test-compile</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjrt</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjtools</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                </dependencies>
-            </plugin>
-            <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-jar-plugin</artifactId>
                 <version>2.4</version>
diff --git a/profiles/killbill/src/main/java/org/killbill/billing/server/security/KillbillJdbcTenantRealm.java b/profiles/killbill/src/main/java/org/killbill/billing/server/security/KillbillJdbcTenantRealm.java
index 2e40851..5cf6470 100644
--- a/profiles/killbill/src/main/java/org/killbill/billing/server/security/KillbillJdbcTenantRealm.java
+++ b/profiles/killbill/src/main/java/org/killbill/billing/server/security/KillbillJdbcTenantRealm.java
@@ -36,6 +36,8 @@ import org.apache.shiro.util.ByteSource;
 import org.killbill.billing.util.config.definition.SecurityConfig;
 import org.killbill.billing.util.security.shiro.KillbillCredentialsMatcher;
 
+import br.ufrgs.inf.prosoft.cache.*;
+
 /**
  * @see {shiro.ini}
  */
@@ -92,8 +94,11 @@ public class KillbillJdbcTenantRealm extends JdbcRealm {
         private static final long serialVersionUID = 4498655519894503985L;
 
         private byte[] bytes;
-        private String cachedHex;
-        private String cachedBase64;
+        // private String cachedHex;
+        // private String cachedBase64;
+private GetterCache<String> cachedHex = new GetterCache<>("KillbillJdbcTenantRealm.cachedHex");
+private GetterCache<String> cachedBase64 = new GetterCache<>("KillbillJdbcTenantRealm.cachedBase64");
+
 
         // For deserialization
         public SerializableSimpleByteSource() {}
@@ -109,18 +114,24 @@ public class KillbillJdbcTenantRealm extends JdbcRealm {
 
         @Override
         public String toHex() {
+            return cachedHex.computeIfAbsent(() -> {
             // if (this.cachedHex == null) {
-                this.cachedHex = Hex.encodeToString(getBytes());
+                // this.cachedHex = Hex.encodeToString(getBytes());
+                return Hex.encodeToString(getBytes());
             // }
-            return this.cachedHex;
+            // return this.cachedHex;
+            });
         }
 
         @Override
         public String toBase64() {
+            return cachedBase64.computeIfAbsent(() -> {
             // if (this.cachedBase64 == null) {
-                this.cachedBase64 = Base64.encodeToString(getBytes());
+                // this.cachedBase64 = Base64.encodeToString(getBytes());
+                return Base64.encodeToString(getBytes());
             // }
-            return this.cachedBase64;
+            // return this.cachedBase64;
+            });
         }
 
         @Override
diff --git a/profiles/killpay/pom.xml b/profiles/killpay/pom.xml
index fab2ff6..2b4cdda 100644
--- a/profiles/killpay/pom.xml
+++ b/profiles/killpay/pom.xml
@@ -190,52 +190,6 @@
     <build>
         <plugins>
             <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>aspectj-maven-plugin</artifactId>
-                <version>1.11</version>
-                <configuration>
-                    <showWeaveInfo>false</showWeaveInfo>
-                    <complianceLevel>1.8</complianceLevel>
-                    <source>1.8</source>
-                    <target>1.8</target>
-                    <Xlint>ignore</Xlint>
-                    <encoding>UTF-8</encoding>
-                    <verbose>false</verbose>
-                    <forceAjcCompile>true</forceAjcCompile>
-                    <sources/>
-                    <weaveDirectories>
-                        <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
-                    </weaveDirectories>
-                    <aspectLibraries>
-                        <aspectLibrary>
-                            <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
-                            <artifactId>ApplicationTracer</artifactId>
-                        </aspectLibrary>
-                    </aspectLibraries>
-                </configuration>
-                <executions>
-                    <execution>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>compile</goal>
-                            <goal>test-compile</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjrt</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjtools</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                </dependencies>
-            </plugin>
-            <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-jar-plugin</artifactId>
                 <version>2.4</version>
diff --git a/subscription/pom.xml b/subscription/pom.xml
index d46a8d6..f6ed771 100644
--- a/subscription/pom.xml
+++ b/subscription/pom.xml
@@ -202,54 +202,4 @@
             <scope>test</scope>
         </dependency>
     </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>aspectj-maven-plugin</artifactId>
-                <version>1.11</version>
-                <configuration>
-                    <showWeaveInfo>false</showWeaveInfo>
-                    <complianceLevel>1.8</complianceLevel>
-                    <source>1.8</source>
-                    <target>1.8</target>
-                    <Xlint>ignore</Xlint>
-                    <encoding>UTF-8</encoding>
-                    <verbose>false</verbose>
-                    <forceAjcCompile>true</forceAjcCompile>
-                    <sources/>
-                    <weaveDirectories>
-                        <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
-                    </weaveDirectories>
-                    <aspectLibraries>
-                        <aspectLibrary>
-                            <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
-                            <artifactId>ApplicationTracer</artifactId>
-                        </aspectLibrary>
-                    </aspectLibraries>
-                </configuration>
-                <executions>
-                    <execution>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>compile</goal>
-                            <goal>test-compile</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjrt</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjtools</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                </dependencies>
-            </plugin>
-       </plugins>
-    </build>
 </project>
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionApiBase.java b/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionApiBase.java
index 5e2441d..c543078 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionApiBase.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionApiBase.java
@@ -60,6 +60,8 @@ import com.google.common.base.Function;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableList;
 
+import br.ufrgs.inf.prosoft.cache.*;
+
 public class SubscriptionApiBase {
 
     protected final SubscriptionDao dao;
@@ -259,6 +261,9 @@ public class SubscriptionApiBase {
         }
     }
 
+
+public static MultiCache<UUID, UUID> accountIdCacheController = new MultiCache<>("SubscriptionApiBase.accountIdCacheController");
+
     protected SubscriptionBaseBundle createBundleForAccount(final UUID accountId,
                                                             final String bundleKey,
                                                             final boolean renameCancelledBundleIfExist,
@@ -272,7 +277,7 @@ public class SubscriptionApiBase {
         }
 
         final SubscriptionBaseBundle subscriptionBundle = dao.createSubscriptionBundle(bundle, catalog, renameCancelledBundleIfExist, context);
-        // accountIdCacheController.putIfAbsent(bundle.getId(), accountId);
+        accountIdCacheController.put(bundle.getId(), accountId);
 
         return subscriptionBundle;
     }
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionBaseCreateApi.java b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionBaseCreateApi.java
index 1d6a38e..39b8eb3 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionBaseCreateApi.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionBaseCreateApi.java
@@ -57,10 +57,14 @@ import org.killbill.clock.Clock;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import br.ufrgs.inf.prosoft.cache.*;
+
 public class DefaultSubscriptionBaseCreateApi extends SubscriptionApiBase {
 
     private static final Logger log = LoggerFactory.getLogger(DefaultSubscriptionBaseCreateApi.class);
 
+public static MultiCache<UUID, UUID> bundleIdCacheController = new MultiCache<>("DefaultSubscriptionBaseCreateApi.bundleIdCacheController");
+
     DefaultSubscriptionBaseCreateApi(final SubscriptionDao dao, final SubscriptionBaseApiService apiService, final Clock clock) {
         super(dao, apiService, clock);
     }
@@ -93,11 +97,11 @@ public class DefaultSubscriptionBaseCreateApi extends SubscriptionApiBase {
                                                                                                              callContext);
 
         // Populate the caches
-        // for (final SubscriptionBaseWithAddOns subscriptionBaseWithAO : subscriptionBaseWithAddOns) {
-        //     for (final SubscriptionBase subscriptionBase : subscriptionBaseWithAO.getSubscriptionBaseList()) {
-        //         bundleIdCacheController.putIfAbsent(subscriptionBase.getId(), subscriptionBaseWithAO.getBundle().getId());
-        //     }
-        // }
+        for (final SubscriptionBaseWithAddOns subscriptionBaseWithAO : subscriptionBaseWithAddOns) {
+            for (final SubscriptionBase subscriptionBase : subscriptionBaseWithAO.getSubscriptionBaseList()) {
+                bundleIdCacheController.put(subscriptionBase.getId(), subscriptionBaseWithAO.getBundle().getId());
+            }
+        }
 
         return subscriptionBaseWithAddOns;
     }
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
index db7324a..98e82fc 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
@@ -94,6 +94,9 @@ import com.google.inject.Inject;
 
 import static org.killbill.billing.util.entity.dao.DefaultPaginationHelper.getEntityPaginationNoException;
 
+import br.ufrgs.inf.prosoft.cache.*;
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
 public class DefaultSubscriptionInternalApi extends DefaultSubscriptionBaseCreateApi implements SubscriptionBaseInternalApi {
 
     private static final Logger log = LoggerFactory.getLogger(DefaultSubscriptionInternalApi.class);
@@ -458,6 +461,7 @@ public class DefaultSubscriptionInternalApi extends DefaultSubscriptionBaseCreat
     public UUID getAccountIdFromBundleId(final UUID bundleId, final InternalTenantContext context) throws SubscriptionBaseApiException {
         // final CacheLoaderArgument arg = createAccountIdFromBundleIdCacheLoaderArgument(context);
         // return accountIdCacheController.get(bundleId, arg);
+      return CacheControllerDispatcher.accountIdCacheController.computeIfAbsent(bundleId, () -> {
         final SubscriptionBaseBundle bundle;
         try {
             bundle = getBundleFromId(bundleId, context);
@@ -466,13 +470,16 @@ public class DefaultSubscriptionInternalApi extends DefaultSubscriptionBaseCreat
             return null;
         }
         return bundle.getAccountId();
+      });
     }
 
     @Override
     public UUID getBundleIdFromSubscriptionId(final UUID subscriptionId, final InternalTenantContext context) throws SubscriptionBaseApiException {
         // final CacheLoaderArgument arg = createBundleIdFromSubscriptionIdCacheLoaderArgument(context);
         // return bundleIdCacheController.get(subscriptionId, arg);
-      return dao.getBundleIdFromSubscriptionId(subscriptionId, context);
+      return CacheControllerDispatcher.bundleIdCacheController.computeIfAbsent(subscriptionId, () -> {
+        return dao.getBundleIdFromSubscriptionId(subscriptionId, context);
+      });
     }
 
     @Override

tenant/pom.xml 50(+0 -50)

diff --git a/tenant/pom.xml b/tenant/pom.xml
index 93eab11..46646cb 100644
--- a/tenant/pom.xml
+++ b/tenant/pom.xml
@@ -183,54 +183,4 @@
             <scope>test</scope>
         </dependency>
     </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>aspectj-maven-plugin</artifactId>
-                <version>1.11</version>
-                <configuration>
-                    <showWeaveInfo>false</showWeaveInfo>
-                    <complianceLevel>1.8</complianceLevel>
-                    <source>1.8</source>
-                    <target>1.8</target>
-                    <Xlint>ignore</Xlint>
-                    <encoding>UTF-8</encoding>
-                    <verbose>false</verbose>
-                    <forceAjcCompile>true</forceAjcCompile>
-                    <sources/>
-                    <weaveDirectories>
-                        <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
-                    </weaveDirectories>
-                    <aspectLibraries>
-                        <aspectLibrary>
-                            <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
-                            <artifactId>ApplicationTracer</artifactId>
-                        </aspectLibrary>
-                    </aspectLibraries>
-                </configuration>
-                <executions>
-                    <execution>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>compile</goal>
-                            <goal>test-compile</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjrt</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjtools</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                </dependencies>
-            </plugin>
-       </plugins>
-    </build>
 </project>
diff --git a/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantUserApi.java b/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantUserApi.java
index d15a8ab..b393344 100644
--- a/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantUserApi.java
+++ b/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantUserApi.java
@@ -39,7 +39,7 @@ import org.killbill.billing.tenant.dao.TenantKVModelDao;
 import org.killbill.billing.tenant.dao.TenantModelDao;
 // 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.cache.CacheControllerDispatcher;
 // import org.killbill.billing.util.cache.CacheLoaderArgument;
 import org.killbill.billing.util.callcontext.CallContext;
 import org.killbill.billing.util.callcontext.InternalCallContextFactory;
@@ -52,6 +52,8 @@ import com.google.inject.Inject;
 
 import org.killbill.billing.tenant.api.TenantInternalApi;
 
+import br.ufrgs.inf.prosoft.cache.*;
+
 public class DefaultTenantUserApi implements TenantUserApi {
 
     //
@@ -62,18 +64,20 @@ public class DefaultTenantUserApi implements TenantUserApi {
     //
     // CACHED_TENANT_KEY is not exposed in the API and is hardcoded here since this is really a implementation choice.
     //
-    // public static final Iterable<TenantKey> CACHED_TENANT_KEY = ImmutableList.<TenantKey>builder()
-    //                                                                          .add(TenantKey.CATALOG_TRANSLATION_)
-    //                                                                          .add(TenantKey.INVOICE_MP_TEMPLATE)
-    //                                                                          .add(TenantKey.INVOICE_TEMPLATE)
-    //                                                                          .add(TenantKey.INVOICE_TRANSLATION_)
-    //                                                                          .add(TenantKey.PLUGIN_CONFIG_)
-    //                                                                          .add(TenantKey.PLUGIN_PAYMENT_STATE_MACHINE_)
-    //                                                                          .add(TenantKey.PUSH_NOTIFICATION_CB).build();
+    public static final Iterable<TenantKey> CACHED_TENANT_KEY = ImmutableList.<TenantKey>builder()
+                                                                             .add(TenantKey.CATALOG_TRANSLATION_)
+                                                                             .add(TenantKey.INVOICE_MP_TEMPLATE)
+                                                                             .add(TenantKey.INVOICE_TEMPLATE)
+                                                                             .add(TenantKey.INVOICE_TRANSLATION_)
+                                                                             .add(TenantKey.PLUGIN_CONFIG_)
+                                                                             .add(TenantKey.PLUGIN_PAYMENT_STATE_MACHINE_)
+                                                                             .add(TenantKey.PUSH_NOTIFICATION_CB).build();
 
     private final TenantDao tenantDao;
     private final InternalCallContextFactory internalCallContextFactory;
+public static MultiCache<String, List<String>> tenantKVCache = new MultiCache<>("DefaultTenantUserApi.tenantKVCache");
     // private final CacheController<String, String> tenantKVCache;
+public static MultiCache<String, Tenant> tenantCache = new MultiCache<>("DefaultTenantUserApi.tenantCache");
     // private final CacheController<String, Tenant> tenantCache;
     private final TenantInternalApi tenantApi;
 
@@ -119,18 +123,21 @@ public class DefaultTenantUserApi implements TenantUserApi {
 
     @Override
     public Tenant getTenantByApiKey(final String key) throws TenantApiException {
-        Tenant tenant = null; //tenantCache.get(key, new CacheLoaderArgument(ObjectType.TENANT));
-
-        try {
-            tenant = tenantApi.getTenantByApiKey(key);
-        } catch (final TenantApiException e) {
-            throw new IllegalStateException("TenantCacheLoader cannot find value for key " + key);
-        }
+        return tenantCache.computeIfAbsent(key, () -> {
+            Tenant tenant = null;
+            try {
+                tenant = tenantApi.getTenantByApiKey(key);
+            } catch (final TenantApiException e) {
+                // throw new IllegalStateException("TenantCacheLoader cannot find value for key " + key);
+                throw new RuntimeException(e);
+            }
 
-        if (tenant == null) {
-            throw new TenantApiException(ErrorCode.TENANT_DOES_NOT_EXIST_FOR_API_KEY, key);
-        }
-        return tenant;
+            if (tenant == null) {
+                // throw new TenantApiException(ErrorCode.TENANT_DOES_NOT_EXIST_FOR_API_KEY, key);
+                throw new RuntimeException();
+            }
+            return tenant;
+        });
     }
 
     @Override
@@ -146,38 +153,38 @@ public class DefaultTenantUserApi implements TenantUserApi {
     @Override
     public List<String> getTenantValuesForKey(final String key, final TenantContext context) throws TenantApiException {
         final InternalTenantContext internalContext = internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(context);
-        // if (!isCachedInTenantKVCache(key)) {
+        if (!isCachedInTenantKVCache(key)) {
             return tenantDao.getTenantValueForKey(key, internalContext);
-        // } else {
-        //     return getCachedTenantValuesForKey(key, internalContext);
-        // }
+        } else {
+            return getCachedTenantValuesForKey(key, internalContext);
+        }
     }
 
     @Override
     public void addTenantKeyValue(final String key, final String value, final CallContext context) throws TenantApiException {
         // Invalidate tenantKVCache after we store (to avoid race conditions). Multi-node invalidation will follow the TenantBroadcast pattern
         final InternalCallContext internalContext = internalCallContextFactory.createInternalCallContextWithoutAccountRecordId(context);
-        // final String tenantKey = getCacheKeyName(key, internalContext);
+        final String tenantKey = getCacheKeyName(key, internalContext);
         tenantDao.addTenantKeyValue(key, value, isSingleValueKey(key), internalContext);
-        // tenantKVCache.remove(tenantKey);
+        tenantKVCache.invalidate(tenantKey);
     }
 
     @Override
     public void updateTenantKeyValue(final String key, final String value, final CallContext context) throws TenantApiException {
         // Invalidate tenantKVCache after we store (to avoid race conditions). Multi-node invalidation will follow the TenantBroadcast pattern
         final InternalCallContext internalContext = internalCallContextFactory.createInternalCallContextWithoutAccountRecordId(context);
-        // final String tenantKey = getCacheKeyName(key, internalContext);
+        final String tenantKey = getCacheKeyName(key, internalContext);
         tenantDao.updateTenantLastKeyValue(key, value, internalContext);
-        // tenantKVCache.remove(tenantKey);
+        tenantKVCache.invalidate(tenantKey);
     }
 
     @Override
     public void deleteTenantKey(final String key, final CallContext context) throws TenantApiException {
         // Invalidate tenantKVCache after we delete (to avoid race conditions). Multi-node invalidation will follow the TenantBroadcast pattern
         final InternalCallContext internalContext = internalCallContextFactory.createInternalCallContextWithoutAccountRecordId(context);
-        // final String tenantKey = getCacheKeyName(key, internalContext);
+        final String tenantKey = getCacheKeyName(key, internalContext);
         tenantDao.deleteTenantKey(key, internalContext);
-        // tenantKVCache.remove(tenantKey);
+        tenantKVCache.invalidate(tenantKey);
     }
 
     @Override
@@ -195,23 +202,25 @@ public class DefaultTenantUserApi implements TenantUserApi {
     }
 
 
-    // private List<String> getCachedTenantValuesForKey(final String key, final InternalTenantContext internalContext) {
-    //     final String tenantKey = getCacheKeyName(key, internalContext);
-    //     final Object cachedTenantValues = tenantKVCache.get(tenantKey, new CacheLoaderArgument(ObjectType.TENANT_KVS));
-    //     if (cachedTenantValues == null) {
-    //         return ImmutableList.<String>of();
-    //     } else {
-    //         // Current, we only cache single-value keys
-    //         return ImmutableList.<String>of((String) cachedTenantValues);
-    //     }
-    // }
-
-    // private String getCacheKeyName(final String key, final InternalTenantContext internalContext) {
-    //     final StringBuilder tenantKey = new StringBuilder(key);
-    //     tenantKey.append(CacheControllerDispatcher.CACHE_KEY_SEPARATOR);
-    //     tenantKey.append(internalContext.getTenantRecordId());
-    //     return tenantKey.toString();
-    // }
+    private List<String> getCachedTenantValuesForKey(final String key, final InternalTenantContext internalContext) {
+        final String tenantKey = getCacheKeyName(key, internalContext);
+        final Object cachedTenantValues = tenantKVCache.computeIfAbsent(tenantKey, () -> {
+            return tenantDao.getTenantValueForKey(tenantKey, internalContext);
+        });
+        if (cachedTenantValues == null) {
+            return ImmutableList.<String>of();
+        } else {
+            // Current, we only cache single-value keys
+            return ImmutableList.<String>of((String) cachedTenantValues);
+        }
+    }
+
+    private String getCacheKeyName(final String key, final InternalTenantContext internalContext) {
+        final StringBuilder tenantKey = new StringBuilder(key);
+        tenantKey.append(CacheControllerDispatcher.CACHE_KEY_SEPARATOR);
+        tenantKey.append(internalContext.getTenantRecordId());
+        return tenantKey.toString();
+    }
 
     private boolean isSingleValueKey(final String key) {
         return Iterables.tryFind(ImmutableList.copyOf(TenantKey.values()), new Predicate<TenantKey>() {
@@ -222,12 +231,12 @@ public class DefaultTenantUserApi implements TenantUserApi {
         }).orNull() != null;
     }
 
-    // private boolean isCachedInTenantKVCache(final String key) {
-    //     return Iterables.tryFind(CACHED_TENANT_KEY, new Predicate<TenantKey>() {
-    //         @Override
-    //         public boolean apply(final TenantKey input) {
-    //             return key.startsWith(input.toString());
-    //         }
-    //     }).orNull() != null;
-    // }
+    private boolean isCachedInTenantKVCache(final String key) {
+        return Iterables.tryFind(CACHED_TENANT_KEY, new Predicate<TenantKey>() {
+            @Override
+            public boolean apply(final TenantKey input) {
+                return key.startsWith(input.toString());
+            }
+        }).orNull() != null;
+    }
 }

util/pom.xml 51(+5 -46)

diff --git a/util/pom.xml b/util/pom.xml
index 6b2334b..fd71597 100644
--- a/util/pom.xml
+++ b/util/pom.xml
@@ -29,6 +29,11 @@
     <name>killbill-util</name>
     <dependencies>
         <dependency>
+            <groupId>br.ufrgs.inf.prosoft.cache</groupId>
+            <artifactId>Cache</artifactId>
+            <version>1.0</version>
+        </dependency>
+        <dependency>
             <groupId>aopalliance</groupId>
             <artifactId>aopalliance</artifactId>
             <scope>provided</scope>
@@ -325,52 +330,6 @@
     <build>
         <plugins>
             <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>aspectj-maven-plugin</artifactId>
-                <version>1.11</version>
-                <configuration>
-                    <showWeaveInfo>false</showWeaveInfo>
-                    <complianceLevel>1.8</complianceLevel>
-                    <source>1.8</source>
-                    <target>1.8</target>
-                    <Xlint>ignore</Xlint>
-                    <encoding>UTF-8</encoding>
-                    <verbose>false</verbose>
-                    <forceAjcCompile>true</forceAjcCompile>
-                    <sources/>
-                    <weaveDirectories>
-                        <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
-                    </weaveDirectories>
-                    <aspectLibraries>
-                        <aspectLibrary>
-                            <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
-                            <artifactId>ApplicationTracer</artifactId>
-                        </aspectLibrary>
-                    </aspectLibraries>
-                </configuration>
-                <executions>
-                    <execution>
-                        <phase>process-classes</phase>
-                        <goals>
-                            <goal>compile</goal>
-                            <goal>test-compile</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjrt</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                    <dependency>
-                        <groupId>org.aspectj</groupId>
-                        <artifactId>aspectjtools</artifactId>
-                        <version>1.9.1</version>
-                    </dependency>
-                </dependencies>
-            </plugin>
-            <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-assembly-plugin</artifactId>
                 <executions>
diff --git a/util/src/main/java/org/killbill/billing/util/audit/dao/DefaultAuditDao.java b/util/src/main/java/org/killbill/billing/util/audit/dao/DefaultAuditDao.java
index 782e4e0..99e369a 100644
--- a/util/src/main/java/org/killbill/billing/util/audit/dao/DefaultAuditDao.java
+++ b/util/src/main/java/org/killbill/billing/util/audit/dao/DefaultAuditDao.java
@@ -61,6 +61,8 @@ import com.google.common.collect.Lists;
 
 import static org.killbill.billing.util.glue.IDBISetup.MAIN_RO_IDBI_NAMED;
 
+import br.ufrgs.inf.prosoft.cache.*;
+
 public class DefaultAuditDao implements AuditDao {
 
     private final DBRouter<NonEntitySqlDao> dbRouter;
@@ -110,6 +112,10 @@ public class DefaultAuditDao implements AuditDao {
     }
 
     private Iterator<AuditLog> buildAuditLogsFromModelDao(final Iterator<AuditLogModelDao> auditLogsForAccountRecordId, final InternalTenantContext tenantContext) {
+
+MultiCache<TableName, Map<Long, UUID>> recordIdIdsCache = new MultiCache<>("DefaultAuditDao.recordIdIdsCache");
+MultiCache<TableName, Map<Long, UUID>> historyRecordIdIdsCache = new MultiCache<>("DefaultAuditDao.historyRecordIdIdsCache");
+
         // final Map<TableName, Map<Long, UUID>> recordIdIdsCache = new HashMap<TableName, Map<Long, UUID>>();
         // final Map<TableName, Map<Long, UUID>> historyRecordIdIdsCache = new HashMap<TableName, Map<Long, UUID>>();
         return Iterators.<AuditLogModelDao, AuditLog>transform(auditLogsForAccountRecordId,
@@ -122,48 +128,49 @@ public class DefaultAuditDao implements AuditDao {
 
                                                                        final NonEntitySqlDao nonEntitySqlDao = dbRouter.onDemand(true);
                                                                        final ObjectType objectType;
-                                                                       final UUID auditedEntityId;
+                                                                       UUID auditedEntityId = null;
                                                                        if (originalTableNameForHistoryTableName != null) {
                                                                            // input point to a history entry
                                                                            objectType = originalTableNameForHistoryTableName.getObjectType();
 
 Iterable<RecordIdIdMappings> mappings = null;
 
-                                                                           // if (historyRecordIdIdsCache.get(originalTableNameForHistoryTableName) == null) {
+
+                                                                           if (!historyRecordIdIdsCache.containsKey(originalTableNameForHistoryTableName)) {
                                                                                if (TableName.ACCOUNT.equals(originalTableNameForHistoryTableName)) {
                                                                                    mappings = nonEntitySqlDao.getHistoryRecordIdIdMappingsForAccountsTable(originalTableNameForHistoryTableName.getTableName(),
                                                                                                                                                                                               input.getTableName().getTableName(),
                                                                                                                                                                                               tenantContext);
-                                                                                   // historyRecordIdIdsCache.put(originalTableNameForHistoryTableName, RecordIdIdMappings.toMap(mappings));
+                                                                                   historyRecordIdIdsCache.put(originalTableNameForHistoryTableName, RecordIdIdMappings.toMap(mappings));
                                                                                } else if (TableName.TAG_DEFINITIONS.equals(originalTableNameForHistoryTableName)) {
                                                                                    mappings = nonEntitySqlDao.getHistoryRecordIdIdMappingsForTablesWithoutAccountRecordId(originalTableNameForHistoryTableName.getTableName(),
                                                                                                                                                                                                              input.getTableName().getTableName(),
                                                                                                                                                                                                              tenantContext);
-                                                                                   // historyRecordIdIdsCache.put(originalTableNameForHistoryTableName, RecordIdIdMappings.toMap(mappings));
+                                                                                   historyRecordIdIdsCache.put(originalTableNameForHistoryTableName, RecordIdIdMappings.toMap(mappings));
                                                                                } else {
                                                                                    mappings = nonEntitySqlDao.getHistoryRecordIdIdMappings(originalTableNameForHistoryTableName.getTableName(),
                                                                                                                                                                               input.getTableName().getTableName(),
                                                                                                                                                                               tenantContext);
-                                                                                   // historyRecordIdIdsCache.put(originalTableNameForHistoryTableName, RecordIdIdMappings.toMap(mappings));
+                                                                                   historyRecordIdIdsCache.put(originalTableNameForHistoryTableName, RecordIdIdMappings.toMap(mappings));
 
                                                                                }
-                                                                           // }
-                                                                               Map<Long, UUID> tomapping = RecordIdIdMappings.toMap(mappings);
+                                                                           }
+
+try {
+                                                                           auditedEntityId = historyRecordIdIdsCache.get(originalTableNameForHistoryTableName).get(input.getTargetRecordId());
+} catch (KeyNotFoundException ex) {}
 
-                                                                           // auditedEntityId = historyRecordIdIdsCache.get(originalTableNameForHistoryTableName).get(input.getTargetRecordId());
-                                                                           auditedEntityId = tomapping.get(input.getTargetRecordId());
                                                                        } else {
                                                                            objectType = input.getTableName().getObjectType();
 
-                                                                           // if (recordIdIdsCache.get(input.getTableName()) == null) {
+                                                                           if (!recordIdIdsCache.containsKey(input.getTableName())) {
                                                                                final Iterable<RecordIdIdMappings> mappings = nonEntitySqlDao.getRecordIdIdMappings(input.getTableName().getTableName(),
                                                                                                                                                                    tenantContext);
-                                                                               // recordIdIdsCache.put(input.getTableName(), RecordIdIdMappings.toMap(mappings));
-                                                                           // }
-                                                                               Map<Long, UUID> tomapping = RecordIdIdMappings.toMap(mappings);
-
-                                                                           // auditedEntityId = recordIdIdsCache.get(input.getTableName()).get(input.getTargetRecordId());
-                                                                           auditedEntityId = tomapping.get(input.getTargetRecordId());
+                                                                               recordIdIdsCache.put(input.getTableName(), RecordIdIdMappings.toMap(mappings));
+                                                                           }
+try{
+                                                                           auditedEntityId = recordIdIdsCache.get(input.getTableName()).get(input.getTargetRecordId());
+} catch (KeyNotFoundException ex) {}
                                                                        }
 
                                                                        return new DefaultAuditLog(input, objectType, auditedEntityId);
@@ -190,6 +197,8 @@ Iterable<RecordIdIdMappings> mappings = null;
         }
     }
 
+public static MultiCache<Parameters, List<AuditLogWithHistory>> getAuditLogsWithHistoryForId = new MultiCache<>("DefaultAuditDao.getAuditLogsWithHistoryForId");
+
     @Override
     public List<AuditLogWithHistory> getAuditLogsWithHistoryForId(final HistorySqlDao transactional, final TableName tableName, final UUID objectId, final AuditLevel auditLevel, final InternalTenantContext context) {
         final TableName historyTableName = tableName.getHistoryTableName();
@@ -203,6 +212,8 @@ Iterable<RecordIdIdMappings> mappings = null;
                 final Long targetRecordId = dbRouter.onDemand(true).getRecordIdFromObject(objectId.toString(), tableName.getTableName());
                 final List<EntityHistoryModelDao> objectHistory = transactional.getHistoryForTargetRecordId(true, targetRecordId, context);
 
+                return getAuditLogsWithHistoryForId.computeIfAbsent(new Parameters(historyTableName.name(), historyTableName.getTableName().toLowerCase(), targetRecordId), () -> {
+
                 return ImmutableList.<AuditLogWithHistory>copyOf(Collections2.transform(entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsViaHistoryForTargetRecordId(historyTableName.name(),
                                                                                                                                                                                       historyTableName.getTableName().toLowerCase(),
                                                                                                                                                                                       targetRecordId,
@@ -223,6 +234,7 @@ Iterable<RecordIdIdMappings> mappings = null;
                                                                                                 return new DefaultAuditLogWithHistory((historyEntity == null ? null : historyEntity.getEntity()), inputAuditLog, tableName.getObjectType(), objectId);
                                                                                             }
                                                                                         }));
+                });
             }
         });
     }
@@ -236,6 +248,8 @@ Iterable<RecordIdIdMappings> mappings = null;
         }
     }
 
+public static MultiCache<Parameters, List<AuditLogModelDao>> getAuditLogsViaHistoryForTargetRecordId = new MultiCache<>("DefaultAuditDao.getAuditLogsViaHistoryForTargetRecordId");
+
     private List<AuditLog> doGetAuditLogsViaHistoryForId(final TableName tableName, final UUID objectId, final AuditLevel auditLevel, final InternalTenantContext context) {
         final TableName historyTableName = tableName.getHistoryTableName();
         if (historyTableName == null) {
@@ -246,23 +260,32 @@ Iterable<RecordIdIdMappings> mappings = null;
         final List<AuditLog> allAuditLogs = transactionalSqlDao.execute(true, new EntitySqlDaoTransactionWrapper<List<AuditLog>>() {
             @Override
             public List<AuditLog> inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
-                final List<AuditLogModelDao> auditLogsViaHistoryForTargetRecordId = entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsViaHistoryForTargetRecordId(historyTableName.name(),
-                                                                                                                                                                                  historyTableName.getTableName().toLowerCase(),
-                                                                                                                                                                                  targetRecordId,
-                                                                                                                                                                                  context);
+                final List<AuditLogModelDao> auditLogsViaHistoryForTargetRecordId = 
+                  getAuditLogsViaHistoryForTargetRecordId.computeIfAbsent(new Parameters(historyTableName.name(), historyTableName.getTableName().toLowerCase(), targetRecordId), () -> {
+
+                    return entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsViaHistoryForTargetRecordId(historyTableName.name(),
+                                                                                                                                                                                    historyTableName.getTableName().toLowerCase(),
+                                                                                                                                                                                    targetRecordId,
+                                                                                                                                                                                    context);
+                  });
                 return buildAuditLogsFromModelDao(auditLogsViaHistoryForTargetRecordId, tableName.getObjectType(), objectId);
             }
         });
         return filterAuditLogs(auditLevel, allAuditLogs);
     }
 
+public static MultiCache<Parameters, List<AuditLogModelDao>> getAuditLogsForTargetRecordId = new MultiCache<>("DefaultAuditDao.getAuditLogsForTargetRecordId");
+
     private List<AuditLog> getAuditLogsForRecordId(final TableName tableName, final UUID auditedEntityId, final Long targetRecordId, final AuditLevel auditLevel, final InternalTenantContext context) {
         final List<AuditLog> allAuditLogs = transactionalSqlDao.execute(true, new EntitySqlDaoTransactionWrapper<List<AuditLog>>() {
             @Override
             public List<AuditLog> inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
-                final List<AuditLogModelDao> auditLogsForTargetRecordId = entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsForTargetRecordId(tableName.name(),
+                final List<AuditLogModelDao> auditLogsForTargetRecordId = 
+                  getAuditLogsForTargetRecordId.computeIfAbsent(new Parameters(tableName.name(), targetRecordId), () -> {
+                    return entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsForTargetRecordId(tableName.name(),
                                                                                                                                                               targetRecordId,
                                                                                                                                                               context);
+              });
                 return buildAuditLogsFromModelDao(auditLogsForTargetRecordId, tableName.getObjectType(), auditedEntityId);
             }
         });
diff --git a/util/src/main/java/org/killbill/billing/util/audit/DefaultAccountAuditLogs.java b/util/src/main/java/org/killbill/billing/util/audit/DefaultAccountAuditLogs.java
index 7105f81..0d34afe 100644
--- a/util/src/main/java/org/killbill/billing/util/audit/DefaultAccountAuditLogs.java
+++ b/util/src/main/java/org/killbill/billing/util/audit/DefaultAccountAuditLogs.java
@@ -30,12 +30,15 @@ import com.google.common.collect.AbstractIterator;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 
+import br.ufrgs.inf.prosoft.cache.*;
+
 public class DefaultAccountAuditLogs implements AccountAuditLogs {
 
     private final UUID accountId;
     private final AuditLevel auditLevel;
     private final List<AuditLog> accountAuditLogs;
 
+private MultiCache<ObjectType, DefaultAccountAuditLogsForObjectType> auditLogsCache = new MultiCache<>("DefaultAccountAuditLogs.auditLogsCache");
     // private final Map<ObjectType, DefaultAccountAuditLogsForObjectType> auditLogsCache = new HashMap<ObjectType, DefaultAccountAuditLogsForObjectType>();
 
     public DefaultAccountAuditLogs(final UUID accountId) {
@@ -126,12 +129,15 @@ public class DefaultAccountAuditLogs implements AccountAuditLogs {
 
     @Override
     public AccountAuditLogsForObjectType getAuditLogs(final ObjectType objectType) {
-        // if (auditLogsCache.get(objectType) == null) {
-            // auditLogsCache.put(objectType, new DefaultAccountAuditLogsForObjectType(auditLevel, new ObjectTypeFilter(objectType, accountAuditLogs.iterator())));
-        // }
-return new DefaultAccountAuditLogsForObjectType(auditLevel, new ObjectTypeFilter(objectType, accountAuditLogs.iterator()));
+        if (!auditLogsCache.containsKey(objectType)) {
+            auditLogsCache.put(objectType, new DefaultAccountAuditLogsForObjectType(auditLevel, new ObjectTypeFilter(objectType, accountAuditLogs.iterator())));
+        }
         // Should never be null
-        // return auditLogsCache.get(objectType);
+        try {
+            return auditLogsCache.get(objectType);
+        } catch (KeyNotFoundException ex) {
+            return null;
+        }
     }
 
     @Override
diff --git a/util/src/main/java/org/killbill/billing/util/bcd/BillCycleDayCalculator.java b/util/src/main/java/org/killbill/billing/util/bcd/BillCycleDayCalculator.java
index ce6656c..3b7f927 100644
--- a/util/src/main/java/org/killbill/billing/util/bcd/BillCycleDayCalculator.java
+++ b/util/src/main/java/org/killbill/billing/util/bcd/BillCycleDayCalculator.java
@@ -33,6 +33,8 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Preconditions;
 
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
 public abstract class BillCycleDayCalculator {
 
     private static final Logger log = LoggerFactory.getLogger(BillCycleDayCalculator.class);
@@ -87,14 +89,9 @@ public abstract class BillCycleDayCalculator {
     private static int calculateOrRetrieveBcdFromSubscription(
         // @Nullable final Map<UUID, Integer> bcdCache,
          final SubscriptionBase subscription, final InternalTenantContext internalTenantContext) {
-        Integer result;// = bcdCache != null ? bcdCache.get(subscription.getId()) : null;
-        // if (result == null) {
-            result = calculateBcdFromSubscription(subscription, internalTenantContext);
-            // if (bcdCache != null) {
-            //     bcdCache.put(subscription.getId(), result);
-            // }
-        // }
-        return result;
+        return CacheControllerDispatcher.bcdCacheController.computeIfAbsent(subscription.getId(), () -> {
+            return calculateBcdFromSubscription(subscription, internalTenantContext);
+        });
     }
 
     private static int calculateBcdFromSubscription(final SubscriptionBase subscription, final InternalTenantContext internalTenantContext) {
diff --git a/util/src/main/java/org/killbill/billing/util/cache/CacheControllerDispatcher.java b/util/src/main/java/org/killbill/billing/util/cache/CacheControllerDispatcher.java
index 0ba2e61..8ca96f8 100644
--- a/util/src/main/java/org/killbill/billing/util/cache/CacheControllerDispatcher.java
+++ b/util/src/main/java/org/killbill/billing/util/cache/CacheControllerDispatcher.java
@@ -14,7 +14,7 @@
  * under the License.
  */
 
-// package org.killbill.billing.util.cache;
+package org.killbill.billing.util.cache;
 
 // import java.util.HashMap;
 // import java.util.Map;
@@ -25,12 +25,29 @@
 // import org.slf4j.Logger;
 // import org.slf4j.LoggerFactory;
 
+import br.ufrgs.inf.prosoft.cache.*;
+import java.util.UUID;
+import java.util.List;
+import org.killbill.billing.account.api.ImmutableAccountData;
+
 // // Kill Bill generic cache dispatcher
-// public class CacheControllerDispatcher {
+public class CacheControllerDispatcher {
 
 //     private static final Logger logger = LoggerFactory.getLogger(CacheControllerDispatcher.class);
 
-//     public static final String CACHE_KEY_SEPARATOR = "::";
+    public static final String CACHE_KEY_SEPARATOR = "::";
+
+public static MultiCache<String, Long> accountRecordIdCacheController = new MultiCache<>("CacheControllerDispatcher.accountRecordIdCacheController");
+public static MultiCache<String, Long> tenantRecordIdCacheController = new MultiCache<>("CacheControllerDispatcher.tenantRecordIdCacheController");
+public static MultiCache<String, Long> recordIdCacheController = new MultiCache<>("CacheControllerDispatcher.recordIdCacheController");
+public static MultiCache<String, List> auditLogViaHistory = new MultiCache<>("CacheControllerDispatcher.auditLogViaHistory");
+public static MultiCache<String, UUID> objectIdCacheController = new MultiCache<>("CacheControllerDispatcher.objectIdCacheController");
+public static MultiCache<String, List> auditLog = new MultiCache<>("CacheControllerDispatcher.auditLog");
+public static MultiCache<UUID, Integer> bcdCacheController = new MultiCache<>("CacheControllerDispatcher.bcdCacheController");
+public static MultiCache<Long, ImmutableAccountData> accountCacheController = new MultiCache<>("CacheControllerDispatcher.accountCacheController");
+public static MultiCache<Long, ImmutableAccountData> accountImmutableCacheController = new MultiCache<>("CacheControllerDispatcher.accountImmutableCacheController");
+public static MultiCache<UUID, UUID> accountIdCacheController = new MultiCache<>("CacheControllerDispatcher.accountIdCacheController");
+public static MultiCache<UUID, UUID> bundleIdCacheController = new MultiCache<>("CacheControllerDispatcher.bundleIdCacheController");
 
 //     private final Map<CacheType, CacheController<Object, Object>> caches;
 
@@ -58,4 +75,4 @@
 //     private static <K, V> CacheController<K, V> cast(final CacheController<?, ?> cache) {
 //         return (CacheController<K, V>) cache;
 //     }
-// }
+}
diff --git a/util/src/main/java/org/killbill/billing/util/callcontext/InternalCallContextFactory.java b/util/src/main/java/org/killbill/billing/util/callcontext/InternalCallContextFactory.java
index ed15ba1..d97e8f0 100644
--- a/util/src/main/java/org/killbill/billing/util/callcontext/InternalCallContextFactory.java
+++ b/util/src/main/java/org/killbill/billing/util/callcontext/InternalCallContextFactory.java
@@ -43,6 +43,8 @@ import org.slf4j.MDC;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Preconditions;
 
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
 // Internal contexts almost always expect accountRecordId and tenantRecordId to be populated
 public class InternalCallContextFactory {
 
@@ -61,6 +63,7 @@ public class InternalCallContextFactory {
     // private final CacheController<String, Long> accountRecordIdCacheController;
     // private final CacheController<String, Long> tenantRecordIdCacheController;
 
+
     @Inject
     public InternalCallContextFactory(@Nullable final ImmutableAccountInternalApi accountInternalApi,
                                       final Clock clock,
@@ -346,7 +349,7 @@ public class InternalCallContextFactory {
     public UUID getAccountId(final UUID objectId, final ObjectType objectType, final TenantContext context) {
         final Long accountRecordId = getAccountRecordIdSafe(objectId, objectType, context);
         if (accountRecordId != null) {
-            return nonEntityDao.retrieveIdFromObject(accountRecordId, ObjectType.ACCOUNT, null);
+            return nonEntityDao.retrieveIdFromObject(accountRecordId, ObjectType.ACCOUNT, CacheControllerDispatcher.objectIdCacheController);
         } else {
             return null;
         }
@@ -356,7 +359,7 @@ public class InternalCallContextFactory {
     public Long getRecordIdFromObject(final UUID objectId, final ObjectType objectType, final TenantContext context) {
         try {
             if (objectBelongsToTheRightTenant(objectId, objectType, context)) {
-                return nonEntityDao.retrieveRecordIdFromObject(objectId, objectType, null);
+                return nonEntityDao.retrieveRecordIdFromObject(objectId, objectType, CacheControllerDispatcher.recordIdCacheController);
             } else {
                 return null;
             }
@@ -397,11 +400,11 @@ public class InternalCallContextFactory {
     }
 
     private UUID getTenantIdSafe(final InternalTenantContext context) {
-        return nonEntityDao.retrieveIdFromObject(context.getTenantRecordId(), ObjectType.TENANT, null);
+        return nonEntityDao.retrieveIdFromObject(context.getTenantRecordId(), ObjectType.TENANT, CacheControllerDispatcher.objectIdCacheController);
     }
 
     private UUID getAccountIdSafe(final InternalTenantContext context) {
-        return context.getAccountRecordId() != null ? nonEntityDao.retrieveIdFromObject(context.getAccountRecordId(), ObjectType.ACCOUNT, null) : null;
+        return context.getAccountRecordId() != null ? nonEntityDao.retrieveIdFromObject(context.getAccountRecordId(), ObjectType.ACCOUNT, CacheControllerDispatcher.objectIdCacheController) : null;
     }
 
     //
@@ -429,11 +432,11 @@ public class InternalCallContextFactory {
     //
 
     private Long getAccountRecordIdUnsafe(final UUID objectId, final ObjectType objectType) {
-        return nonEntityDao.retrieveAccountRecordIdFromObject(objectId, objectType, null);
+        return nonEntityDao.retrieveAccountRecordIdFromObject(objectId, objectType, CacheControllerDispatcher.tenantRecordIdCacheController);
     }
 
     private Long getTenantRecordIdUnsafe(final UUID objectId, final ObjectType objectType) {
-        return nonEntityDao.retrieveTenantRecordIdFromObject(objectId, objectType, null);
+        return nonEntityDao.retrieveTenantRecordIdFromObject(objectId, objectType, CacheControllerDispatcher.tenantRecordIdCacheController);
     }
 
     public static final class ObjectDoesNotExist extends IllegalStateException {
diff --git a/util/src/main/java/org/killbill/billing/util/config/tenant/MultiTenantConfigBase.java b/util/src/main/java/org/killbill/billing/util/config/tenant/MultiTenantConfigBase.java
index 0cd2544..8fd9b7a 100644
--- a/util/src/main/java/org/killbill/billing/util/config/tenant/MultiTenantConfigBase.java
+++ b/util/src/main/java/org/killbill/billing/util/config/tenant/MultiTenantConfigBase.java
@@ -32,8 +32,12 @@ import com.google.common.base.Function;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 
+import br.ufrgs.inf.prosoft.cache.*;
+
 public abstract class MultiTenantConfigBase {
 
+MultiCache<String, Method> methodsCache = new MultiCache<>("MultiTenantConfigBase.methodsCache");
+
     // private final Map<String, Method> methodsCache = new HashMap<String, Method>();
     // protected final CacheConfig cacheConfig;
 
@@ -116,22 +120,13 @@ public abstract class MultiTenantConfigBase {
     }
 
     protected Method getConfigStaticMethod(final String methodName) {
-        // Method method = methodsCache.get(methodName);
-        Method method = null;
-        // if (method == null) {
-            // synchronized (methodsCache) {
-                // method = methodsCache.get(methodName);
-                // if (method == null) {
-                    try {
-                        method = getConfigClass().getMethod(methodName, InternalTenantContext.class);
-                        // methodsCache.put(methodName, method);
-                    } catch (final NoSuchMethodException e) {
-                        throw new RuntimeException(e);
-                    }
-                // }
-            // }
-        // }
-        return method;
+        return methodsCache.computeIfAbsent(methodName, () -> {
+           try {
+                return getConfigClass().getMethod(methodName, InternalTenantContext.class);
+            } catch (final NoSuchMethodException e) {
+                throw new RuntimeException(e);
+            }
+        });
     }
 
     protected abstract Class<? extends KillbillConfig> getConfigClass();
diff --git a/util/src/main/java/org/killbill/billing/util/dao/DefaultNonEntityDao.java b/util/src/main/java/org/killbill/billing/util/dao/DefaultNonEntityDao.java
index 7ebb1c4..b7a90e4 100644
--- a/util/src/main/java/org/killbill/billing/util/dao/DefaultNonEntityDao.java
+++ b/util/src/main/java/org/killbill/billing/util/dao/DefaultNonEntityDao.java
@@ -41,25 +41,27 @@ import com.google.common.base.Preconditions;
 
 import static org.killbill.billing.util.glue.IDBISetup.MAIN_RO_IDBI_NAMED;
 
+import br.ufrgs.inf.prosoft.cache.*;
+
 public class DefaultNonEntityDao implements NonEntityDao {
 
     private final DBRouter<NonEntitySqlDao> dbRouter;
-    private final WithCaching<String, Long> withCachingObjectId;
-    private final WithCaching<String, UUID> withCachingRecordId;
+    // private final WithCaching<String, Long> withCachingObjectId;
+    // private final WithCaching<String, UUID> withCachingRecordId;
 
     @Inject
     public DefaultNonEntityDao(final IDBI dbi, @Named(MAIN_RO_IDBI_NAMED) final IDBI roDbi) {
         this.dbRouter = new DBRouter<NonEntitySqlDao>(dbi, roDbi, NonEntitySqlDao.class);
-        this.withCachingObjectId = new WithCaching<String, Long>();
-        this.withCachingRecordId = new WithCaching<String, UUID>();
+        // this.withCachingObjectId = new WithCaching<String, Long>();
+        // this.withCachingRecordId = new WithCaching<String, UUID>();
     }
 
     @Override
-    public Long retrieveRecordIdFromObject(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Object cache) {
+    public Long retrieveRecordIdFromObject(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache) {
         return retrieveRecordIdFromObjectInTransaction(objectId, objectType, cache, null);
     }
 
-    public Long retrieveRecordIdFromObjectInTransaction(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Object cache, @Nullable final Handle handle) {
+    public Long retrieveRecordIdFromObjectInTransaction(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache, @Nullable final Handle handle) {
         if (objectId == null) {
             return null;
         }
@@ -67,29 +69,33 @@ public class DefaultNonEntityDao implements NonEntityDao {
         final TableName tableName = TableName.fromObjectType(objectType);
         Preconditions.checkNotNull(tableName, "%s is not a valid ObjectType", objectType);
 
-        return withCachingObjectId.withCaching(new OperationRetrieval<Long>() {
-            @Override
-            public Long doRetrieve(final ObjectType objectType) {
+        // return withCachingObjectId.withCaching(new OperationRetrieval<Long>() {
+            // @Override
+            // public Long doRetrieve(final ObjectType objectType) {
+        return cache.computeIfAbsent(objectId.toString(), () -> {
                 final NonEntitySqlDao inTransactionNonEntitySqlDao = handle == null ? dbRouter.onDemand(true) : SqlObjectBuilder.attach(handle, NonEntitySqlDao.class);
                 return inTransactionNonEntitySqlDao.getRecordIdFromObject(objectId.toString(), tableName.getTableName());
-            }
-        }, objectId.toString(), objectType, tableName, cache);
+        });
+            // }
+        // }, objectId.toString(), objectType, tableName, cache);
     }
 
     @Override
-    public Long retrieveAccountRecordIdFromObject(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Object cache) {
+    public Long retrieveAccountRecordIdFromObject(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache) {
         return retrieveAccountRecordIdFromObjectInTransaction(objectId, objectType, cache, null);
     }
 
     @Override
-    public Long retrieveAccountRecordIdFromObjectInTransaction(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Object cache, @Nullable final Handle handle) {
+    public Long retrieveAccountRecordIdFromObjectInTransaction(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache, @Nullable final Handle handle) {
         final TableName tableName = TableName.fromObjectType(objectType);
         Preconditions.checkNotNull(tableName, "%s is not a valid ObjectType", objectType);
 
         final String objectIdOrNull = objectId != null ? objectId.toString() : null;
-        return withCachingObjectId.withCaching(new OperationRetrieval<Long>() {
-            @Override
-            public Long doRetrieve(final ObjectType objectType) {
+        return cache.computeIfAbsent(objectIdOrNull, () -> {
+
+        // withCachingObjectId.withCaching(new OperationRetrieval<Long>() {
+            // @Override
+            // public Long doRetrieve(final ObjectType objectType) {
                 final NonEntitySqlDao inTransactionNonEntitySqlDao = handle == null ? dbRouter.onDemand(true) : SqlObjectBuilder.attach(handle, NonEntitySqlDao.class);
 
                 switch (tableName) {
@@ -104,24 +110,26 @@ public class DefaultNonEntityDao implements NonEntityDao {
                     default:
                         return inTransactionNonEntitySqlDao.getAccountRecordIdFromObjectOtherThanAccount(objectIdOrNull, tableName.getTableName());
                 }
-            }
-        }, objectIdOrNull, objectType, tableName, cache);
+        });
+            // }
+        // }, objectIdOrNull, objectType, tableName, cache);
     }
 
     @Override
-    public Long retrieveTenantRecordIdFromObject(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Object cache) {
+    public Long retrieveTenantRecordIdFromObject(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache) {
         return retrieveTenantRecordIdFromObjectInTransaction(objectId, objectType, cache, null);
     }
 
     @Override
-    public Long retrieveTenantRecordIdFromObjectInTransaction(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Object cache, @Nullable final Handle handle) {
+    public Long retrieveTenantRecordIdFromObjectInTransaction(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache, @Nullable final Handle handle) {
         final TableName tableName = TableName.fromObjectType(objectType);
         Preconditions.checkNotNull(tableName, "%s is not a valid ObjectType", objectType);
 
         final String objectIdOrNull = objectId != null ? objectId.toString() : null;
-        return withCachingObjectId.withCaching(new OperationRetrieval<Long>() {
-            @Override
-            public Long doRetrieve(final ObjectType objectType) {
+        return cache.computeIfAbsent(objectIdOrNull, () -> {
+        // withCachingObjectId.withCaching(new OperationRetrieval<Long>() {
+            // @Override
+            // public Long doRetrieve(final ObjectType objectType) {
                 final NonEntitySqlDao inTransactionNonEntitySqlDao = handle == null ? dbRouter.onDemand(true) : SqlObjectBuilder.attach(handle, NonEntitySqlDao.class);
 
                 switch (tableName) {
@@ -133,17 +141,18 @@ public class DefaultNonEntityDao implements NonEntityDao {
                         return inTransactionNonEntitySqlDao.getTenantRecordIdFromObjectOtherThanTenant(objectIdOrNull, tableName.getTableName());
                 }
 
-            }
-        }, objectIdOrNull, objectType, tableName, cache);
+            // }
+        });
+        // }, objectIdOrNull, objectType, tableName, cache);
     }
 
     @Override
-    public UUID retrieveIdFromObject(final Long recordId, final ObjectType objectType, @Nullable final Object cache) {
+    public UUID retrieveIdFromObject(final Long recordId, final ObjectType objectType, @Nullable final Cache<String, UUID> cache) {
         return retrieveIdFromObjectInTransaction(recordId, objectType, cache, null);
     }
 
     @Override
-    public UUID retrieveIdFromObjectInTransaction(final Long recordId, final ObjectType objectType, @Nullable final Object cache, @Nullable final Handle handle) {
+    public UUID retrieveIdFromObjectInTransaction(final Long recordId, final ObjectType objectType, @Nullable final Cache<String, UUID> cache, @Nullable final Handle handle) {
         if (objectType == ObjectType.TENANT && InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID.equals(recordId)) {
             return null;
         }
@@ -151,13 +160,15 @@ public class DefaultNonEntityDao implements NonEntityDao {
         final TableName tableName = TableName.fromObjectType(objectType);
         Preconditions.checkNotNull(tableName, "%s is not a valid ObjectType", objectType);
 
-        return withCachingRecordId.withCaching(new OperationRetrieval<UUID>() {
-            @Override
-            public UUID doRetrieve(final ObjectType objectType) {
+        return cache.computeIfAbsent(String.valueOf(recordId), () -> {
+        // withCachingRecordId.withCaching(new OperationRetrieval<UUID>() {
+            // @Override
+            // public UUID doRetrieve(final ObjectType objectType) {
                 final NonEntitySqlDao inTransactionNonEntitySqlDao = handle == null ? dbRouter.onDemand(true) : SqlObjectBuilder.attach(handle, NonEntitySqlDao.class);
                 return inTransactionNonEntitySqlDao.getIdFromObject(recordId, tableName.getTableName());
-            }
-        }, String.valueOf(recordId), objectType, tableName, cache);
+            // }
+        // }, String.valueOf(recordId), objectType, tableName, cache);
+        });
     }
 
     @Override
@@ -171,34 +182,34 @@ public class DefaultNonEntityDao implements NonEntityDao {
         return dbRouter.onDemand(true).getHistoryTargetRecordId(recordId, tableName.getTableName());
     }
 
-    private interface OperationRetrieval<TypeOut> {
+    // private interface OperationRetrieval<TypeOut> {
 
-        public TypeOut doRetrieve(final ObjectType objectType);
-    }
+    //     public TypeOut doRetrieve(final ObjectType objectType);
+    // }
 
     // 'cache' will be null for the CacheLoader classes -- or if cache is not configured.
-    private class WithCaching<TypeIn, TypeOut> {
+    // private class WithCaching<TypeIn, TypeOut> {
 
-        private TypeOut withCaching(final OperationRetrieval<TypeOut> op, @Nullable final TypeIn objectOrRecordId, final ObjectType objectType, final TableName tableName, @Nullable final Object cache) {
+        // private TypeOut withCaching(final OperationRetrieval<TypeOut> op, @Nullable final TypeIn objectOrRecordId, final ObjectType objectType, final TableName tableName, @Nullable final Cache<TypeIn, TypeOut> cache) {
 
-            final Profiling<TypeOut, RuntimeException> prof = new Profiling<TypeOut, RuntimeException>();
-            if (objectOrRecordId == null) {
-                return null;
-            }
+            // final Profiling<TypeOut, RuntimeException> prof = new Profiling<TypeOut, RuntimeException>();
+            // if (objectOrRecordId == null) {
+            //     return null;
+            // }
             // if (cache != null) {
-            //     final TypeIn key = (cache.getCacheType().isKeyPrefixedWithTableName()) ?
-            //                        (TypeIn) (tableName + CacheControllerDispatcher.CACHE_KEY_SEPARATOR + objectOrRecordId.toString()) :
-            //                        objectOrRecordId;
-            //     return cache.get(key, new CacheLoaderArgument(objectType));
+                // final TypeIn key = //(cache.getCacheType().isKeyPrefixedWithTableName()) ?
+                //                    (TypeIn) (tableName + CacheControllerDispatcher.CACHE_KEY_SEPARATOR + objectOrRecordId.toString());// :
+                //                    // objectOrRecordId;
+                // return cache.get(key);
             // }
-            final TypeOut result;
-            result = prof.executeWithProfiling(ProfilingFeatureType.DAO_DETAILS, "NonEntityDao (type = " + objectType + ") cache miss", new WithProfilingCallback<TypeOut, RuntimeException>() {
-                @Override
-                public TypeOut execute() throws RuntimeException {
-                    return op.doRetrieve(objectType);
-                }
-            });
-            return result;
-        }
-    }
+            // final TypeOut result;
+            // result = prof.executeWithProfiling(ProfilingFeatureType.DAO_DETAILS, "NonEntityDao (type = " + objectType + ") cache miss", new WithProfilingCallback<TypeOut, RuntimeException>() {
+                // @Override
+                // public TypeOut execute() throws RuntimeException {
+                    // return op.doRetrieve(objectType);
+                // }
+            // });
+            // return result;
+    //     }
+    // }
 }
diff --git a/util/src/main/java/org/killbill/billing/util/dao/NonEntityDao.java b/util/src/main/java/org/killbill/billing/util/dao/NonEntityDao.java
index 19142be..b646efe 100644
--- a/util/src/main/java/org/killbill/billing/util/dao/NonEntityDao.java
+++ b/util/src/main/java/org/killbill/billing/util/dao/NonEntityDao.java
@@ -26,24 +26,26 @@ import org.killbill.billing.ObjectType;
 // import org.killbill.billing.util.cache.CacheController;
 import org.skife.jdbi.v2.Handle;
 
+import br.ufrgs.inf.prosoft.cache.*;
+
 // This should only be used for internal operations (trusted code, not API), because the context will not be validated!
 public interface NonEntityDao {
 
-    public Long retrieveRecordIdFromObject(final UUID objectId, final ObjectType objectType, @Nullable final Object cache);
+    public Long retrieveRecordIdFromObject(final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache);
 
-    public Long retrieveRecordIdFromObjectInTransaction(final UUID objectId, final ObjectType objectType, @Nullable final Object cache, @Nullable final Handle handle);
+    public Long retrieveRecordIdFromObjectInTransaction(final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache, @Nullable final Handle handle);
 
-    public Long retrieveAccountRecordIdFromObject(final UUID objectId, final ObjectType objectType, @Nullable final Object cache);
+    public Long retrieveAccountRecordIdFromObject(final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache);
 
-    public Long retrieveAccountRecordIdFromObjectInTransaction(final UUID objectId, final ObjectType objectType, @Nullable final Object cache, @Nullable final Handle handle);
+    public Long retrieveAccountRecordIdFromObjectInTransaction(final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache, @Nullable final Handle handle);
 
-    public Long retrieveTenantRecordIdFromObject(final UUID objectId, final ObjectType objectType, @Nullable final Object cache);
+    public Long retrieveTenantRecordIdFromObject(final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache);
 
-    public Long retrieveTenantRecordIdFromObjectInTransaction(final UUID objectId, final ObjectType objectType, @Nullable final Object cache, @Nullable final Handle handle);
+    public Long retrieveTenantRecordIdFromObjectInTransaction(final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache, @Nullable final Handle handle);
 
-    public UUID retrieveIdFromObject(final Long recordId, final ObjectType objectType, @Nullable final Object cache);
+    public UUID retrieveIdFromObject(final Long recordId, final ObjectType objectType, @Nullable final Cache<String, UUID> cache);
 
-    public UUID retrieveIdFromObjectInTransaction(final Long recordId, final ObjectType objectType, @Nullable final Object cache, @Nullable final Handle handle);
+    public UUID retrieveIdFromObjectInTransaction(final Long recordId, final ObjectType objectType, @Nullable final Cache<String, UUID> cache, @Nullable final Handle handle);
 
     // This retrieves from the history table the latest record for which targetId matches the one we are passing
     public Long retrieveLastHistoryRecordIdFromTransaction(final Long targetRecordId, final TableName tableName, final NonEntitySqlDao transactional);
diff --git a/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java b/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java
index 1154593..aea6772 100644
--- a/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java
+++ b/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java
@@ -75,6 +75,8 @@ import com.google.common.collect.ImmutableList.Builder;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
 /**
  * Wraps an instance of EntitySqlDao, performing extra work around each method (Sql query)
  *
@@ -212,9 +214,9 @@ public class EntitySqlDaoWrapperInvocationHandler<S extends EntitySqlDao<M, E>, 
                 // the object after it was created, which means this method is (by pattern) first called right after object creation and contains all the goodies we care
                 // about (record_id, account_record_id, object_id, tenant_record_id)
                 //
-                // if (result != null && method.getName().equals("getById")) {
-                    // populateCacheOnGetByIdInvocation((M) result);
-                // }
+                if (result != null && method.getName().equals("getById")) {
+                    populateCacheOnGetByIdInvocation((M) result);
+                }
                 return result;
             }
         });
@@ -371,33 +373,30 @@ public class EntitySqlDaoWrapperInvocationHandler<S extends EntitySqlDao<M, E>, 
         }
     }
 
-    // private void populateCacheOnGetByIdInvocation(final M model) {
-    //     populateCaches(cacheControllerDispatcher, model);
-    // }
-
-    // public static void populateCaches(final CacheControllerDispatcher cacheControllerDispatcher, final EntityModelDao model) {
-    //     final CacheController<String, Long> cacheRecordId = cacheControllerDispatcher.getCacheController(CacheType.RECORD_ID);
-    //     cacheRecordId.putIfAbsent(getKey(model.getId().toString(), CacheType.RECORD_ID, model.getTableName()), model.getRecordId());
-
-    //     final CacheController<String, UUID> cacheObjectId = cacheControllerDispatcher.getCacheController(CacheType.OBJECT_ID);
-    //     cacheObjectId.putIfAbsent(getKey(model.getRecordId().toString(), CacheType.OBJECT_ID, model.getTableName()), model.getId());
+    private void populateCacheOnGetByIdInvocation(final M model) {
+        populateCaches(//cacheControllerDispatcher, 
+            model);
+    }
 
-    //     if (model.getTenantRecordId() != null) {
-    //         final CacheController<String, Long> cacheTenantRecordId = cacheControllerDispatcher.getCacheController(CacheType.TENANT_RECORD_ID);
-    //         cacheTenantRecordId.putIfAbsent(getKey(model.getId().toString(), CacheType.TENANT_RECORD_ID, model.getTableName()), model.getTenantRecordId());
-    //     }
+    public static void populateCaches(
+        //final CacheControllerDispatcher cacheControllerDispatcher, 
+        final EntityModelDao model) {
+        CacheControllerDispatcher.recordIdCacheController.put(getKey(model.getId().toString(), "CacheType.RECORD_ID", model.getTableName()), model.getRecordId());
+        CacheControllerDispatcher.objectIdCacheController.put(getKey(model.getRecordId().toString(), "CacheType.OBJECT_ID", model.getTableName()), model.getId());
+        if (model.getTenantRecordId() != null) {
+            CacheControllerDispatcher.tenantRecordIdCacheController.put(getKey(model.getId().toString(), "CacheType.TENANT_RECORD_ID", model.getTableName()), model.getTenantRecordId());
+        }
 
-    //     if (model.getAccountRecordId() != null) {
-    //         final CacheController<String, Long> cacheAccountRecordId = cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_RECORD_ID);
-    //         cacheAccountRecordId.putIfAbsent(getKey(model.getId().toString(), CacheType.ACCOUNT_RECORD_ID, model.getTableName()), model.getAccountRecordId());
-    //     }
-    // }
+        if (model.getAccountRecordId() != null) {
+            CacheControllerDispatcher.accountRecordIdCacheController.put(getKey(model.getId().toString(), "CacheType.ACCOUNT_RECORD_ID", model.getTableName()), model.getAccountRecordId());
+        }
+    }
 
-    // private static String getKey(final String rawKey, final CacheType cacheType, final TableName tableName) {
-    //     return cacheType.isKeyPrefixedWithTableName() ?
-    //            tableName + CacheControllerDispatcher.CACHE_KEY_SEPARATOR + rawKey :
-    //            rawKey;
-    // }
+    private static String getKey(final String rawKey, final String cacheType, final TableName tableName) {
+        return //cacheType.isKeyPrefixedWithTableName() ?
+               tableName + CacheControllerDispatcher.CACHE_KEY_SEPARATOR + rawKey ;//:
+               //rawKey;
+    }
 
     private M updateHistoryAndAudit(final String entityId, @Nullable final M deletedEntity, final ChangeType changeType, final InternalCallContext context) throws Throwable {
         final Object reHydratedEntity = prof.executeWithProfiling(ProfilingFeatureType.DAO_DETAILS, getProfilingId("history/audit", null), new WithProfilingCallback<Object, Throwable>() {
@@ -528,35 +527,29 @@ public class EntitySqlDaoWrapperInvocationHandler<S extends EntitySqlDao<M, E>, 
 
         // We need to invalidate the caches. There is a small window of doom here where caches will be stale.
         // TODO Knowledge on how the key is constructed is also in AuditSqlDao
-        // if (tableName.getHistoryTableName() != null) {
-            // final CacheController<String, List> cacheController = cacheControllerDispatcher.getCacheController(CacheType.AUDIT_LOG_VIA_HISTORY);
-            // if (cacheController != null) {
-            //     final String key = buildCacheKey(ImmutableMap.<Integer, Object>of(0, tableName.getHistoryTableName(), 1, tableName.getHistoryTableName(), 2, entityRecordId));
-            //     cacheController.remove(key);
-            // }
-        // } else {
-            // final CacheController<String, List> cacheController = cacheControllerDispatcher.getCacheController(CacheType.AUDIT_LOG);
-            // if (cacheController != null) {
-            //     final String key = buildCacheKey(ImmutableMap.<Integer, Object>of(0, tableName, 1, entityRecordId));
-            //     cacheController.remove(key);
-            // }
-        // }
+        if (tableName.getHistoryTableName() != null) {
+                final String key = buildCacheKey(ImmutableMap.<Integer, Object>of(0, tableName.getHistoryTableName(), 1, tableName.getHistoryTableName(), 2, entityRecordId));
+                CacheControllerDispatcher.auditLogViaHistory.invalidate(key);
+        } else {
+                final String key = buildCacheKey(ImmutableMap.<Integer, Object>of(0, tableName, 1, entityRecordId));
+                CacheControllerDispatcher.auditLog.invalidate(key);
+        }
     }
 
-    // private String buildCacheKey(final Map<Integer, Object> keyPieces) {
-    //     final StringBuilder cacheKey = new StringBuilder();
-    //     for (int i = 0; i < keyPieces.size(); i++) {
-    //         // To normalize the arguments and avoid casing issues, we make all pieces of the key uppercase.
-    //         // Since the database engine may be case insensitive and we use arguments of the SQL method call
-    //         // to build the key, the key has to be case insensitive as well.
-    //         final String str = String.valueOf(keyPieces.get(i)).toUpperCase();
-    //         cacheKey.append(str);
-    //         if (i < keyPieces.size() - 1) {
-    //             cacheKey.append(CacheControllerDispatcher.CACHE_KEY_SEPARATOR);
-    //         }
-    //     }
-    //     return cacheKey.toString();
-    // }
+    private String buildCacheKey(final Map<Integer, Object> keyPieces) {
+        final StringBuilder cacheKey = new StringBuilder();
+        for (int i = 0; i < keyPieces.size(); i++) {
+            // To normalize the arguments and avoid casing issues, we make all pieces of the key uppercase.
+            // Since the database engine may be case insensitive and we use arguments of the SQL method call
+            // to build the key, the key has to be case insensitive as well.
+            final String str = String.valueOf(keyPieces.get(i)).toUpperCase();
+            cacheKey.append(str);
+            if (i < keyPieces.size() - 1) {
+                cacheKey.append(CacheControllerDispatcher.CACHE_KEY_SEPARATOR);
+            }
+        }
+        return cacheKey.toString();
+    }
 
     private String getProfilingId(@Nullable final String prefix, @Nullable final Method method) {
         final StringBuilder stringBuilder = new StringBuilder().append(sqlDaoClass.getSimpleName());
diff --git a/util/src/main/java/org/killbill/billing/util/security/AnnotationHierarchicalResolver.java b/util/src/main/java/org/killbill/billing/util/security/AnnotationHierarchicalResolver.java
index dc8a72f..a72d353 100644
--- a/util/src/main/java/org/killbill/billing/util/security/AnnotationHierarchicalResolver.java
+++ b/util/src/main/java/org/killbill/billing/util/security/AnnotationHierarchicalResolver.java
@@ -25,6 +25,8 @@ import java.util.WeakHashMap;
 import org.apache.shiro.aop.AnnotationResolver;
 import org.apache.shiro.aop.MethodInvocation;
 
+import br.ufrgs.inf.prosoft.cache.*;
+
 public class AnnotationHierarchicalResolver implements AnnotationResolver {
 
     private final Map<String, Annotation> methodToAnnotation = new HashMap<String, Annotation>();
@@ -122,9 +124,12 @@ public class AnnotationHierarchicalResolver implements AnnotationResolver {
         return annotation;
     }
 
+
+public static MultiCache<Class<?>, Boolean> isInterfaceWithAnnotatedMethods = new MultiCache<>("AnnotationHierarchicalResolver.isInterfaceWithAnnotatedMethods");
     // private static final Map<Class<?>, Boolean> annotatedInterfaceCache = new WeakHashMap<Class<?>, Boolean>();
 
     private static boolean isInterfaceWithAnnotatedMethods(final Class<?> iface) {
+return isInterfaceWithAnnotatedMethods.computeIfAbsent(iface, () -> {
         // synchronized (annotatedInterfaceCache) {
             // final Boolean flag = annotatedInterfaceCache.get(iface);
             // if (flag != null) {
@@ -139,6 +144,7 @@ public class AnnotationHierarchicalResolver implements AnnotationResolver {
             }
             // annotatedInterfaceCache.put(iface, found);
             return found;
+}, 20000);
         }
     // }
 }