keycloak-uncached

Merge pull request #217 from mposolda/master Use UUID for

2/18/2014 7:48:20 AM

Changes

pom.xml 45(+45 -0)

Details

diff --git a/docbook/reference/en/en-US/modules/Overview.xml b/docbook/reference/en/en-US/modules/Overview.xml
index 8e970c7..bdd3b2b 100755
--- a/docbook/reference/en/en-US/modules/Overview.xml
+++ b/docbook/reference/en/en-US/modules/Overview.xml
@@ -78,7 +78,7 @@
             Once a user is logged in, they can visit any other application managed by the realm and not have to re-enter
             credentials.  This also hold true for logging out.  Roles can also be defined at the application level and
             assigned to specific users.  Depending on the application type, you may also be able to view and manage
-            user sessions from the adminstration console.
+            user sessions from the administration console.
         </para>
         <para>
             An <emphasis>oauth client</emphasis> is similar to an application in that it can request something like a login
diff --git a/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java b/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java
index 4582a03..b814d7f 100644
--- a/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java
@@ -6,6 +6,7 @@ import java.security.Key;
 import java.security.PrivateKey;
 import java.security.PublicKey;
 import java.util.Set;
+import java.util.UUID;
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.bouncycastle.openssl.PEMWriter;
@@ -25,7 +26,7 @@ public final class KeycloakModelUtils {
     private static AtomicLong counter = new AtomicLong(1);
 
     public static String generateId() {
-        return counter.getAndIncrement() + "-" + System.currentTimeMillis();
+        return UUID.randomUUID().toString();
     }
 
     public static PublicKey getPublicKey(String publicKeyPem) {
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AbstractRoleMappingEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AbstractRoleMappingEntity.java
index c840453..101d558 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AbstractRoleMappingEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AbstractRoleMappingEntity.java
@@ -1,11 +1,12 @@
 package org.keycloak.models.jpa.entities;
 
 import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.MappedSuperclass;
 
+import org.hibernate.annotations.GenericGenerator;
+
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
@@ -13,18 +14,19 @@ import javax.persistence.MappedSuperclass;
 @MappedSuperclass
 public class AbstractRoleMappingEntity {
     @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
-    protected long id;
+    @GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
+    @GeneratedValue(generator = "keycloak_generator")
+    protected String id;
     @ManyToOne
     protected UserEntity user;
     @ManyToOne
     protected RoleEntity role;
 
-    public long getId() {
+    public String getId() {
         return id;
     }
 
-    public void setId(long id) {
+    public void setId(String id) {
         this.id = id;
     }
 
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ApplicationEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ApplicationEntity.java
index 667fd48..5da99fc 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ApplicationEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ApplicationEntity.java
@@ -4,7 +4,6 @@ import javax.persistence.CascadeType;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.JoinTable;
 import javax.persistence.OneToMany;
@@ -12,6 +11,8 @@ import javax.persistence.OneToOne;
 import java.util.ArrayList;
 import java.util.Collection;
 
+import org.hibernate.annotations.GenericGenerator;
+
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
@@ -19,7 +20,8 @@ import java.util.Collection;
 @Entity
 public class ApplicationEntity {
     @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
+    @GeneratedValue(generator = "keycloak_generator")
     private String id;
 
     private String name;
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/CredentialEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/CredentialEntity.java
index ec110b8..e42eefe 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/CredentialEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/CredentialEntity.java
@@ -2,12 +2,13 @@ package org.keycloak.models.jpa.entities;
 
 import javax.persistence.Entity;
 import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
 
+import org.hibernate.annotations.GenericGenerator;
+
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
@@ -18,7 +19,8 @@ import javax.persistence.NamedQuery;
 @Entity
 public class CredentialEntity {
     @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
+    @GeneratedValue(generator = "keycloak_generator")
     protected String id;
 
     protected String type;
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/OAuthClientEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/OAuthClientEntity.java
index 9d440c3..d266ed7 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/OAuthClientEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/OAuthClientEntity.java
@@ -3,13 +3,14 @@ package org.keycloak.models.jpa.entities;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
 import javax.persistence.OneToOne;
 
+import org.hibernate.annotations.GenericGenerator;
+
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
@@ -22,7 +23,8 @@ import javax.persistence.OneToOne;
 @Entity
 public class OAuthClientEntity {
     @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
+    @GeneratedValue(generator = "keycloak_generator")
     private String id;
 
     private String name;
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RequiredCredentialEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RequiredCredentialEntity.java
index 8a35808..9487022 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RequiredCredentialEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RequiredCredentialEntity.java
@@ -2,9 +2,10 @@ package org.keycloak.models.jpa.entities;
 
 import javax.persistence.Entity;
 import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
 import javax.persistence.Id;
 
+import org.hibernate.annotations.GenericGenerator;
+
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
@@ -12,7 +13,8 @@ import javax.persistence.Id;
 @Entity
 public class RequiredCredentialEntity {
     @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
+    @GeneratedValue(generator = "keycloak_generator")
     protected String id;
 
     protected String type;
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java
index 1c21d12..acb40c9 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java
@@ -3,7 +3,6 @@ package org.keycloak.models.jpa.entities;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.Inheritance;
 import javax.persistence.InheritanceType;
@@ -13,6 +12,8 @@ import javax.persistence.OneToMany;
 import java.util.ArrayList;
 import java.util.Collection;
 
+import org.hibernate.annotations.GenericGenerator;
+
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
@@ -21,7 +22,8 @@ import java.util.Collection;
 @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
 public abstract class RoleEntity {
     @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
+    @GeneratedValue(generator = "keycloak_generator")
     private String id;
 
     private String name;
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/SocialLinkEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/SocialLinkEntity.java
index ccc0a59..9063948 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/SocialLinkEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/SocialLinkEntity.java
@@ -8,6 +8,9 @@ import javax.persistence.ManyToOne;
 import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
 
+import org.hibernate.annotations.GenericGenerator;
+import org.keycloak.models.jpa.utils.JpaIdGenerator;
+
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
@@ -20,8 +23,11 @@ import javax.persistence.NamedQuery;
 @Entity
 public class SocialLinkEntity {
     @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
-    private long id;
+    @GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
+    @GeneratedValue(generator = "keycloak_generator")
+    private String id;
+
+    private String str = JpaIdGenerator.class.getName();
 
     @ManyToOne
     private UserEntity user;
@@ -32,11 +38,11 @@ public class SocialLinkEntity {
     protected String socialProvider;
     protected String socialUsername;
 
-    public long getId() {
+    public String getId() {
         return id;
     }
 
-    public void setId(long id) {
+    public void setId(String id) {
         this.id = id;
     }
 
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java
index bcddabd..04af485 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java
@@ -1,5 +1,6 @@
 package org.keycloak.models.jpa.entities;
 
+import org.hibernate.annotations.GenericGenerator;
 import org.keycloak.models.UserModel;
 
 import javax.persistence.CascadeType;
@@ -35,7 +36,8 @@ import java.util.Set;
 @Entity
 public class UserEntity {
     @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @GenericGenerator(name="uuid_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
+    @GeneratedValue(generator = "uuid_generator")
     protected String id;
 
     protected String loginName;
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java
index a072c75..1a24530 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java
@@ -83,12 +83,12 @@ public class JpaKeycloakSession implements KeycloakSession {
             adapter.removeApplication(a.getId());
         }
 
+        em.createQuery("delete from " + OAuthClientEntity.class.getSimpleName() + " where realm = :realm").setParameter("realm", realm).executeUpdate();
+
         for (UserEntity u : em.createQuery("from UserEntity", UserEntity.class).getResultList()) {
             adapter.removeUser(u.getLoginName());
         }
 
-        em.createQuery("delete from " + OAuthClientEntity.class.getSimpleName() + " where realm = :realm").setParameter("realm", realm).executeUpdate();
-
         em.remove(realm);
 
         return true;
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaModelProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaModelProvider.java
index 629f795..03473e5 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaModelProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaModelProvider.java
@@ -1,5 +1,9 @@
 package org.keycloak.models.jpa;
 
+import java.util.Map;
+import java.util.Properties;
+
+import org.jboss.resteasy.logging.Logger;
 import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.models.ModelProvider;
 
@@ -19,8 +23,21 @@ public class JpaModelProvider implements ModelProvider {
 
     @Override
     public KeycloakSessionFactory createFactory() {
-        EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpa-keycloak-identity-store");
+        EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpa-keycloak-identity-store", getHibernateProperties());
         return new JpaKeycloakSessionFactory(emf);
 
     }
+
+    // Allows to override some properties in persistence.xml by system properties
+    protected Properties getHibernateProperties() {
+        Properties result = new Properties();
+
+        for (Object property : System.getProperties().keySet()) {
+            if (property.toString().startsWith("hibernate.")) {
+                String propValue = System.getProperty(property.toString());
+                result.put(property, propValue);
+            }
+        }
+        return result;
+    }
 }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/utils/JpaIdGenerator.java b/model/jpa/src/main/java/org/keycloak/models/jpa/utils/JpaIdGenerator.java
new file mode 100644
index 0000000..6fc10e8
--- /dev/null
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/utils/JpaIdGenerator.java
@@ -0,0 +1,19 @@
+package org.keycloak.models.jpa.utils;
+
+import java.io.Serializable;
+
+import org.hibernate.HibernateException;
+import org.hibernate.engine.spi.SessionImplementor;
+import org.hibernate.id.IdentifierGenerator;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class JpaIdGenerator implements IdentifierGenerator {
+
+    @Override
+    public Serializable generate(SessionImplementor session, Object object) throws HibernateException {
+        return KeycloakModelUtils.generateId();
+    }
+}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/impl/MongoStoreImpl.java b/model/mongo/src/main/java/org/keycloak/models/mongo/impl/MongoStoreImpl.java
index f0e135e..fa41a46 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/impl/MongoStoreImpl.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/impl/MongoStoreImpl.java
@@ -6,7 +6,6 @@ import com.mongodb.DB;
 import com.mongodb.DBCollection;
 import com.mongodb.DBCursor;
 import com.mongodb.DBObject;
-import org.bson.types.ObjectId;
 import org.jboss.logging.Logger;
 import org.keycloak.models.mongo.api.MongoCollection;
 import org.keycloak.models.mongo.api.MongoEntity;
@@ -27,6 +26,7 @@ import org.keycloak.models.mongo.impl.types.MapMapper;
 import org.keycloak.models.mongo.impl.types.MongoEntityMapper;
 import org.keycloak.models.mongo.impl.types.SimpleMapper;
 import org.keycloak.models.mongo.impl.types.StringToEnumMapper;
+import org.keycloak.models.utils.KeycloakModelUtils;
 import org.picketlink.common.properties.Property;
 import org.picketlink.common.properties.query.AnnotatedPropertyCriteria;
 import org.picketlink.common.properties.query.PropertyQueries;
@@ -120,17 +120,16 @@ public class MongoStoreImpl implements MongoStore {
 
         String currentId = entity.getId();
 
-        // Inserting object, which already has oid property set. So we need to set "_id"
-        if (currentId != null) {
-            dbObject.put("_id", getObjectId(currentId));
+        // Generate random ID if not set already
+        if (currentId == null) {
+            currentId = KeycloakModelUtils.generateId();
+            entity.setId(currentId);
         }
 
-        dbCollection.insert(dbObject);
+        // Adding "_id"
+        dbObject.put("_id", currentId);
 
-        // Add id to value of given object
-        if (currentId == null) {
-            entity.setId(dbObject.getString("_id"));
-        }
+        dbCollection.insert(dbObject);
 
         // Treat object as created in this transaction (It is already submited to transaction)
         context.addCreatedEntity(entity);
@@ -152,7 +151,7 @@ public class MongoStoreImpl implements MongoStore {
                 if (currentId == null) {
                     throw new IllegalStateException("Can't update entity without id: " + entity);
                 } else {
-                    BasicDBObject query = new BasicDBObject("_id", getObjectId(currentId));
+                    BasicDBObject query = new BasicDBObject("_id", currentId);
                     dbCollection.update(query, dbObject);
                 }
             }
@@ -176,7 +175,7 @@ public class MongoStoreImpl implements MongoStore {
 
         DBCollection dbCollection = getDBCollectionForType(type);
 
-        BasicDBObject idQuery = new BasicDBObject("_id", getObjectId(id));
+        BasicDBObject idQuery = new BasicDBObject("_id", id);
         DBObject dbObject = dbCollection.findOne(idQuery);
 
         if (dbObject == null) return null;
@@ -193,14 +192,16 @@ public class MongoStoreImpl implements MongoStore {
 
     @Override
     public <T extends MongoIdentifiableEntity> T loadSingleEntity(Class<T> type, DBObject query, MongoStoreInvocationContext context) {
-        List<T> result = loadEntities(type, query, context);
-        if (result.size() > 1) {
-            throw new IllegalStateException("There are " + result.size() + " results for type=" + type + ", query=" + query + ". We expect just one");
-        } else if (result.size() == 1) {
-            return result.get(0);
-        } else {
-            // 0 results
+        // First we should execute all pending tasks before searching DB
+        context.beforeDBSearch(type);
+
+        DBCollection dbCollection = getDBCollectionForType(type);
+        DBObject dbObject = dbCollection.findOne(query);
+
+        if (dbObject == null) {
             return null;
+        } else {
+            return convertDBObjectToEntity(type, dbObject, context);
         }
     }
 
@@ -230,7 +231,7 @@ public class MongoStoreImpl implements MongoStore {
             return false;
         } else {
             DBCollection dbCollection = getDBCollectionForType(type);
-            BasicDBObject dbQuery = new BasicDBObject("_id", getObjectId(id));
+            BasicDBObject dbQuery = new BasicDBObject("_id", id);
             dbCollection.remove(dbQuery);
             logger.info("Entity of type: " + type + ", id: " + id + " removed from MongoDB.");
 
@@ -291,7 +292,7 @@ public class MongoStoreImpl implements MongoStore {
                 // Now DB update of new list with usage of $set
                 BasicDBList dbList = mapperRegistry.convertApplicationObjectToDBObject(listt, BasicDBList.class);
 
-                BasicDBObject query = new BasicDBObject("_id", getObjectId(entity.getId()));
+                BasicDBObject query = new BasicDBObject("_id", entity.getId());
                 BasicDBObject listObject = new BasicDBObject(listPropertyName, dbList);
                 BasicDBObject setCommand = new BasicDBObject("$set", listObject);
                 getDBCollectionForType(type).update(query, setCommand);
@@ -334,7 +335,7 @@ public class MongoStoreImpl implements MongoStore {
                 public void execute() {
                     // Pull item from DB
                     Object dbItemToPull = mapperRegistry.convertApplicationObjectToDBObject(itemToPull, Object.class);
-                    BasicDBObject query = new BasicDBObject("_id", getObjectId(entity.getId()));
+                    BasicDBObject query = new BasicDBObject("_id", entity.getId());
                     BasicDBObject pullObject = new BasicDBObject(listPropertyName, dbItemToPull);
                     BasicDBObject pullCommand = new BasicDBObject("$pull", pullObject);
                     getDBCollectionForType(type).update(query, pullCommand);
@@ -350,7 +351,7 @@ public class MongoStoreImpl implements MongoStore {
         }
     }
 
-    // Possibility to add user-defined converters
+    // Possibility to add user-defined mappers
     public void addAppObjectConverter(Mapper<?, ?> mapper) {
         mapperRegistry.addAppObjectMapper(mapper);
     }
@@ -383,17 +384,7 @@ public class MongoStoreImpl implements MongoStore {
 
         try {
             for (DBObject dbObject : cursor) {
-                // First look if we already have loaded object cached. If yes, we will use cached instance
-                String id = dbObject.get("_id").toString();
-                T entity = context.getLoadedEntity(type, id);
-
-                if (entity == null) {
-                    // So convert and use fresh instance from DB
-                    MapperContext<Object, T> mapperContext = new MapperContext<Object, T>(dbObject, type, null);
-                    entity = mapperRegistry.convertDBObjectToApplicationObject(mapperContext);
-                    context.addLoadedEntity(entity);
-                }
-
+                T entity = convertDBObjectToEntity(type, dbObject, context);
                 result.add(entity);
             }
         } finally {
@@ -403,18 +394,23 @@ public class MongoStoreImpl implements MongoStore {
         return result;
     }
 
+    protected <T extends MongoIdentifiableEntity> T convertDBObjectToEntity(Class<T> type, DBObject dbObject, MongoStoreInvocationContext context) {
+        // First look if we already have loaded object cached. If yes, we will use cached instance
+        String id = dbObject.get("_id").toString();
+        T object = context.getLoadedEntity(type, id);
+
+        if (object == null) {
+            // So convert and use fresh instance from DB
+            MapperContext<Object, T> mapperContext = new MapperContext<Object, T>(dbObject, type, null);
+            object = mapperRegistry.convertDBObjectToApplicationObject(mapperContext);
+            context.addLoadedEntity(object);
+        }
+        return object;
+    }
+
     protected DBCollection getDBCollectionForType(Class<? extends MongoEntity> type) {
         EntityInfo entityInfo = getEntityInfo(type);
         String dbCollectionName = entityInfo.getDbCollectionName();
-        return dbCollectionName==null ? null : database.getCollection(entityInfo.getDbCollectionName());
-    }
-
-    // We allow ObjectId to be both "ObjectId" or "String".
-    protected Object getObjectId(String idAsString) {
-        if (ObjectId.isValid(idAsString)) {
-            return new ObjectId(idAsString);
-        } else {
-            return idAsString;
-        }
+        return dbCollectionName==null ? null : database.getCollection(dbCollectionName);
     }
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RoleAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RoleAdapter.java
index a3ed40b..0436569 100644
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RoleAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RoleAdapter.java
@@ -90,7 +90,7 @@ public class RoleAdapter extends AbstractAdapter implements RoleModel {
         }
 
         DBObject query = new QueryBuilder()
-                .and("_id").in(MongoModelUtils.convertStringsToObjectIds(role.getCompositeRoleIds()))
+                .and("_id").in(role.getCompositeRoleIds())
                 .get();
         List<RoleEntity> childRoles = getMongoStore().loadEntities(RoleEntity.class, query, invocationContext);
 
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java b/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java
index 4be29ec..b7a9a21 100644
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java
@@ -19,14 +19,6 @@ import org.keycloak.models.mongo.keycloak.entities.UserEntity;
  */
 public class MongoModelUtils {
 
-    public static List<ObjectId> convertStringsToObjectIds(Collection<String> strings) {
-        List<ObjectId> result = new ArrayList<ObjectId>();
-        for (String id : strings) {
-            result.add(new ObjectId(id));
-        }
-        return result;
-    }
-
     // Get everything including both application and realm roles
     public static List<RoleEntity> getAllRolesOfUser(UserModel user, MongoStoreInvocationContext invContext) {
         UserEntity userEntity = ((UserAdapter)user).getUser();
@@ -37,7 +29,7 @@ public class MongoModelUtils {
         }
 
         DBObject query = new QueryBuilder()
-                .and("_id").in(convertStringsToObjectIds(roleIds))
+                .and("_id").in(roleIds)
                 .get();
         return invContext.getMongoStore().loadEntities(RoleEntity.class, query, invContext);
     }
@@ -52,7 +44,7 @@ public class MongoModelUtils {
         }
 
         DBObject query = new QueryBuilder()
-                .and("_id").in(convertStringsToObjectIds(scopeIds))
+                .and("_id").in(scopeIds)
                 .get();
         return invContext.getMongoStore().loadEntities(RoleEntity.class, query, invContext);
     }
diff --git a/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java b/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java
index 1f2fda1..f334236 100644
--- a/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java
@@ -40,6 +40,14 @@ public class AbstractModelTest {
         factory.close();
     }
 
+    protected void commit() {
+        identitySession.getTransaction().commit();
+        identitySession.close();
+        identitySession = factory.createSession();
+        identitySession.getTransaction().begin();
+        realmManager = new RealmManager(identitySession);
+    }
+
     public static RealmRepresentation loadJson(String path) throws IOException {
         InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
         ByteArrayOutputStream os = new ByteArrayOutputStream();
diff --git a/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java b/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java
index 6bd1f07..cd18852 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java
@@ -96,11 +96,7 @@ public class AdapterTest extends AbstractModelTest {
         String id = realmModel.getId();
         System.out.println("id: " + id);
 
-        identitySession.getTransaction().commit();
-        identitySession.close();
-        identitySession = factory.createSession();
-        identitySession.getTransaction().begin();
-        realmManager = new RealmManager(identitySession);
+        commit();
         List<RealmModel> realms = identitySession.getRealms(null);
         System.out.println("num realms: " + realms.size());
         Assert.assertEquals(realms.size(), 1);
diff --git a/model/tests/src/test/java/org/keycloak/model/test/CompositeRolesModelTest.java b/model/tests/src/test/java/org/keycloak/model/test/CompositeRolesModelTest.java
index 1baf83e..ec14411 100644
--- a/model/tests/src/test/java/org/keycloak/model/test/CompositeRolesModelTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/CompositeRolesModelTest.java
@@ -28,48 +28,29 @@ public class CompositeRolesModelTest extends AbstractModelTest {
     }
 
     @Test
-    public void testAppComposites() {
+    public void testComposites() {
         Set<RoleModel> requestedRoles = getRequestedRoles("APP_COMPOSITE_APPLICATION", "APP_COMPOSITE_USER");
-
         Assert.assertEquals(2, requestedRoles.size());
         assertContains("APP_ROLE_APPLICATION", "APP_ROLE_1", requestedRoles);
         assertContains("realm", "REALM_ROLE_1", requestedRoles);
-    }
-
-    @Test
-    public void testRealmAppComposites() {
-        Set<RoleModel> requestedRoles = getRequestedRoles("APP_COMPOSITE_APPLICATION", "REALM_APP_COMPOSITE_USER");
 
+        requestedRoles = getRequestedRoles("APP_COMPOSITE_APPLICATION", "REALM_APP_COMPOSITE_USER");
         Assert.assertEquals(1, requestedRoles.size());
         assertContains("APP_ROLE_APPLICATION", "APP_ROLE_1", requestedRoles);
-    }
-
-    @Test
-    public void testRealmOnlyWithUserCompositeAppComposite() throws Exception {
-        Set<RoleModel> requestedRoles = getRequestedRoles("REALM_COMPOSITE_1_APPLICATION", "REALM_COMPOSITE_1_USER");
 
+        requestedRoles = getRequestedRoles("REALM_COMPOSITE_1_APPLICATION", "REALM_COMPOSITE_1_USER");
         Assert.assertEquals(1, requestedRoles.size());
         assertContains("realm", "REALM_COMPOSITE_1", requestedRoles);
-    }
-
-    @Test
-    public void testRealmOnlyWithUserCompositeAppRole() throws Exception {
-        Set<RoleModel> requestedRoles = getRequestedRoles("REALM_ROLE_1_APPLICATION", "REALM_COMPOSITE_1_USER");
 
+        requestedRoles = getRequestedRoles("REALM_ROLE_1_APPLICATION", "REALM_COMPOSITE_1_USER");
         Assert.assertEquals(1, requestedRoles.size());
         assertContains("realm", "REALM_ROLE_1", requestedRoles);
-    }
-
-    @Test
-    public void testRealmOnlyWithUserRoleAppComposite() throws Exception {
-        Set<RoleModel> requestedRoles = getRequestedRoles("REALM_COMPOSITE_1_APPLICATION", "REALM_ROLE_1_USER");
 
+        requestedRoles = getRequestedRoles("REALM_COMPOSITE_1_APPLICATION", "REALM_ROLE_1_USER");
         Assert.assertEquals(1, requestedRoles.size());
         assertContains("realm", "REALM_ROLE_1", requestedRoles);
     }
 
-    // TODO: more tests...
-
     // Same algorithm as in TokenManager.createAccessCode
     private Set<RoleModel> getRequestedRoles(String applicationName, String username) {
         Set<RoleModel> requestedRoles = new HashSet<RoleModel>();
diff --git a/model/tests/src/test/java/org/keycloak/model/test/UserModelTest.java b/model/tests/src/test/java/org/keycloak/model/test/UserModelTest.java
index 6567e19..89bc061 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/UserModelTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/UserModelTest.java
@@ -99,14 +99,6 @@ public class UserModelTest extends AbstractModelTest {
         Assert.assertTrue(user.getRequiredActions().isEmpty());
     }
 
-    protected void commit() {
-        identitySession.getTransaction().commit();
-        identitySession.close();
-        identitySession = factory.createSession();
-        identitySession.getTransaction().begin();
-        realmManager = new RealmManager(identitySession);
-    }
-
     public static void assertEquals(UserModel expected, UserModel actual) {
         Assert.assertEquals(expected.getLoginName(), actual.getLoginName());
         Assert.assertEquals(expected.getFirstName(), actual.getFirstName());

pom.xml 45(+45 -0)

diff --git a/pom.xml b/pom.xml
index 2f4bab5..8e5632e 100755
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,10 @@
         <hibernate.javax.persistence.version>1.0.1.Final</hibernate.javax.persistence.version>
         <hibernate.entitymanager.version>4.0.1.Final</hibernate.entitymanager.version>
         <h2.version>1.3.161</h2.version>
+        <mysql.version>5.1.29</mysql.version>
+        <postgresql.version>9.3-1100-jdbc41</postgresql.version>
         <dom4j.version>1.6.1</dom4j.version>
+        <xml-apis.version>1.4.01</xml-apis.version>
         <mysql.version>5.1.25</mysql.version>
         <slf4j.version>1.6.1</slf4j.version>
         <jboss.version>7.1.1.Final</jboss.version>
@@ -324,6 +327,11 @@
                 <version>${dom4j.version}</version>
             </dependency>
             <dependency>
+                <groupId>xml-apis</groupId>
+                <artifactId>xml-apis</artifactId>
+                <version>${xml-apis.version}</version>
+            </dependency>
+            <dependency>
                 <groupId>org.slf4j</groupId>
                 <artifactId>slf4j-api</artifactId>
                 <version>${slf4j.version}</version>
@@ -544,5 +552,42 @@
                 <module>distribution</module>
             </modules>
         </profile>
+
+        <!-- MySQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>hibernate.connection.driver_class</name>
+                    <value>com.mysql.jdbc.Driver</value>
+                </property>
+            </activation>
+            <id>mysql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>mysql</groupId>
+                    <artifactId>mysql-connector-java</artifactId>
+                    <version>${mysql.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+        <!-- PostgreSQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>hibernate.connection.driver_class</name>
+                    <value>org.postgresql.Driver</value>
+                </property>
+            </activation>
+            <id>postgresql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>org.postgresql</groupId>
+                    <artifactId>postgresql</artifactId>
+                    <version>${postgresql.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
     </profiles>
 </project>
diff --git a/server/src/main/java/org/keycloak/server/KeycloakServerApplication.java b/server/src/main/java/org/keycloak/server/KeycloakServerApplication.java
index fdcdaa4..fc9331a 100755
--- a/server/src/main/java/org/keycloak/server/KeycloakServerApplication.java
+++ b/server/src/main/java/org/keycloak/server/KeycloakServerApplication.java
@@ -29,7 +29,6 @@ public class KeycloakServerApplication extends KeycloakApplication {
             session.getTransaction().begin();
             RealmRepresentation rep = loadJson(new FileInputStream(importRealm), RealmRepresentation.class);
             importRealm(session, rep);
-            session.getTransaction().commit();
         }
 
         String themeDir = System.getProperty("keycloak.theme.dir");
diff --git a/testsuite/integration/pom.xml b/testsuite/integration/pom.xml
index d668ee8..d1d1d5a 100755
--- a/testsuite/integration/pom.xml
+++ b/testsuite/integration/pom.xml
@@ -232,12 +232,10 @@
         <dependency>
             <groupId>com.h2database</groupId>
             <artifactId>h2</artifactId>
-            <version>1.3.161</version>
         </dependency>
         <dependency>
             <groupId>org.hibernate</groupId>
             <artifactId>hibernate-entitymanager</artifactId>
-            <version>3.6.6.Final</version>
         </dependency>
         <dependency>
             <groupId>com.icegreen</groupId>
@@ -248,6 +246,10 @@
             <artifactId>selenium-java</artifactId>
         </dependency>
         <dependency>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.seleniumhq.selenium</groupId>
             <artifactId>selenium-chrome-driver</artifactId>
         </dependency>
diff --git a/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java b/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
index ebd181b..6fbb6fd 100755
--- a/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
+++ b/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
@@ -96,7 +96,7 @@ public class KeycloakServer {
         }
     }
 
-    private static <T> T loadJson(InputStream is, Class<T> type) {
+    public static <T> T loadJson(InputStream is, Class<T> type) {
         try {
             return JsonSerialization.readValue(is, type);
         } catch (IOException e) {
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeImportRoleTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeImportRoleTest.java
index ddd15ed..dfb2fc9 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeImportRoleTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeImportRoleTest.java
@@ -41,6 +41,7 @@ import org.keycloak.testsuite.pages.LoginPage;
 import org.keycloak.testsuite.rule.AbstractKeycloakRule;
 import org.keycloak.testsuite.rule.WebResource;
 import org.keycloak.testsuite.rule.WebRule;
+import org.keycloak.testutils.KeycloakServer;
 import org.openqa.selenium.WebDriver;
 
 import java.security.PublicKey;
@@ -55,11 +56,11 @@ public class CompositeImportRoleTest {
     public static AbstractKeycloakRule keycloakRule = new AbstractKeycloakRule(){
         @Override
         protected void configure(RealmManager manager, RealmModel adminRealm) {
-            server.importRealm(getClass().getResourceAsStream("/testcomposite.json"));
-            RealmModel realm = manager.getRealmByName("Test");
-            realmPublicKey = realm.getPublicKey();
-
+            RealmModel realm = manager.createRealm("Test");
+            RealmRepresentation representation = KeycloakServer.loadJson(getClass().getResourceAsStream("/testcomposite.json"), RealmRepresentation.class);
+            manager.importRealm(representation, realm);
 
+            realmPublicKey = realm.getPublicKey();
 
             deployServlet("app", "/app", ApplicationServlet.class);