keycloak-uncached

realm cache event

10/20/2016 12:35:28 PM

Details

diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java
index 99b718c..4647f74 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java
@@ -52,7 +52,7 @@ import java.util.Set;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class CachedRealm extends AbstractRevisioned {
+public class CachedRealm extends AbstractExtendableRevisioned {
 
     protected String name;
     protected String displayName;
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java
index 4802a6b..4406731 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java
@@ -36,6 +36,7 @@ import org.keycloak.models.RequiredCredentialModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserFederationMapperModel;
 import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.cache.CachedRealmModel;
 import org.keycloak.models.cache.infinispan.entities.CachedRealm;
 import org.keycloak.models.utils.KeycloakModelUtils;
 
@@ -50,12 +51,13 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class RealmAdapter implements RealmModel {
+public class RealmAdapter implements CachedRealmModel {
     protected CachedRealm cached;
     protected RealmCacheSession cacheSession;
     protected RealmModel updated;
@@ -66,17 +68,32 @@ public class RealmAdapter implements RealmModel {
         this.cacheSession = cacheSession;
     }
 
-    protected void getDelegateForUpdate() {
+    @Override
+    public RealmModel getDelegateForUpdate() {
         if (updated == null) {
             cacheSession.registerRealmInvalidation(cached.getId());
             updated = cacheSession.getDelegate().getRealm(cached.getId());
             if (updated == null) throw new IllegalStateException("Not found in database");
         }
+        return updated;
     }
 
     protected boolean invalidated;
+
+    @Override
     public void invalidate() {
         invalidated = true;
+        getDelegateForUpdate();
+    }
+
+    @Override
+    public long getCacheTimestamp() {
+        return cached.getCacheTimestamp();
+    }
+
+    @Override
+    public ConcurrentHashMap getCachedWith() {
+        return cached.getCachedWith();
     }
 
     protected boolean isUpdated() {
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java
index 6cd91a5..418b264 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java
@@ -29,6 +29,7 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.models.RealmProvider;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.cache.CacheRealmProvider;
+import org.keycloak.models.cache.CachedRealmModel;
 import org.keycloak.models.cache.infinispan.entities.CachedClient;
 import org.keycloak.models.cache.infinispan.entities.CachedClientRole;
 import org.keycloak.models.cache.infinispan.entities.CachedClientTemplate;
@@ -374,6 +375,7 @@ public class RealmCacheSession implements CacheRealmProvider {
         if (cached != null) {
             logger.tracev("by id cache hit: {0}", cached.getName());
         }
+        boolean wasCached = false;
         if (cached == null) {
             Long loaded = cache.getCurrentRevision(id);
             RealmModel model = getDelegate().getRealm(id);
@@ -381,12 +383,27 @@ public class RealmCacheSession implements CacheRealmProvider {
             if (invalidations.contains(id)) return model;
             cached = new CachedRealm(loaded, model);
             cache.addRevisioned(cached, startupRevision);
+            wasCached =true;
         } else if (invalidations.contains(id)) {
             return getDelegate().getRealm(id);
         } else if (managedRealms.containsKey(id)) {
             return managedRealms.get(id);
         }
         RealmAdapter adapter = new RealmAdapter(cached, this);
+        if (wasCached) {
+            CachedRealmModel.RealmCachedEvent event = new CachedRealmModel.RealmCachedEvent() {
+                @Override
+                public CachedRealmModel getRealm() {
+                    return adapter;
+                }
+
+                @Override
+                public KeycloakSession getKeycloakSession() {
+                    return session;
+                }
+            };
+            session.getKeycloakSessionFactory().publish(event);
+        }
         managedRealms.put(id, adapter);
         return adapter;
     }
diff --git a/server-spi/src/main/java/org/keycloak/models/cache/CachedRealmModel.java b/server-spi/src/main/java/org/keycloak/models/cache/CachedRealmModel.java
new file mode 100644
index 0000000..16a965f
--- /dev/null
+++ b/server-spi/src/main/java/org/keycloak/models/cache/CachedRealmModel.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.models.cache;
+
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.provider.ProviderEvent;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Cached realms will implement this interface
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface CachedRealmModel extends RealmModel {
+
+    interface RealmCachedEvent extends ProviderEvent {
+        CachedRealmModel getRealm();
+        KeycloakSession getKeycloakSession();
+    }
+
+    /**
+     * Invalidates the cache for this model and returns a delegate that represents the actual data provider
+     *
+     * @return
+     */
+    RealmModel getDelegateForUpdate();
+
+    /**
+     * Invalidate the cache for this model
+     *
+     */
+    void invalidate();
+
+    /**
+     * When was the model was loaded from database.
+     *
+     * @return
+     */
+    long getCacheTimestamp();
+
+    /**
+     * Returns a map that contains custom things that are cached along with this model.  You can write to this map.
+     *
+     * @return
+     */
+    ConcurrentHashMap getCachedWith();
+}
diff --git a/server-spi/src/main/java/org/keycloak/models/cache/CachedUserModel.java b/server-spi/src/main/java/org/keycloak/models/cache/CachedUserModel.java
index 9ee5a6a..67431a9 100644
--- a/server-spi/src/main/java/org/keycloak/models/cache/CachedUserModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/cache/CachedUserModel.java
@@ -36,20 +36,20 @@ public interface CachedUserModel extends UserModel {
     UserModel getDelegateForUpdate();
 
     /**
-     * Invalidate the cache for this user
+     * Invalidate the cache for this model
      *
      */
     void invalidate();
 
     /**
-     * When was the user loaded from database.
+     * When was the model was loaded from database.
      *
      * @return
      */
     long getCacheTimestamp();
 
     /**
-     * Returns a map that contains custom things that are cached along with the user.  You can write to this map.
+     * Returns a map that contains custom things that are cached along with this model.  You can write to this map.
      *
      * @return
      */