keycloak-aplcache

Moved model unit tests from services to model/tests . Mongo

2/10/2014 2:36:46 PM

Changes

model/jpa/pom.xml 30(+30 -0)

model/mongo/pom.xml 80(+73 -7)

model/mongo/src/main/java/org/keycloak/models/mongo/api/types/TypeConverter.java 115(+0 -115)

model/mongo/src/main/java/org/keycloak/models/mongo/utils/EmbeddedMongo.java 50(+0 -50)

model/pom.xml 1(+1 -0)

model/tests/pom.xml 69(+69 -0)

pom.xml 12(+6 -6)

services/pom.xml 65(+0 -65)

services/src/test/java/org/keycloak/test/AbstractKeycloakServerTest.java 70(+0 -70)

Details

model/jpa/pom.xml 30(+30 -0)

diff --git a/model/jpa/pom.xml b/model/jpa/pom.xml
index 7ba6691..ecbf289 100755
--- a/model/jpa/pom.xml
+++ b/model/jpa/pom.xml
@@ -59,6 +59,20 @@
                 </exclusion>
             </exclusions>
         </dependency>
+
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-tests</artifactId>
+            <version>${project.version}</version>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+            <scope>test</scope>
+        </dependency>
+
     </dependencies>
     <build>
         <plugins>
@@ -70,6 +84,22 @@
                     <target>1.6</target>
                 </configuration>
             </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>default-test</id>
+                        <configuration>
+                            <dependenciesToScan>
+                                <dependency>org.keycloak:keycloak-model-tests</dependency>
+                            </dependenciesToScan>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
         </plugins>
     </build>
 

model/mongo/pom.xml 80(+73 -7)

diff --git a/model/mongo/pom.xml b/model/mongo/pom.xml
index d1b5952..fadcc7f 100755
--- a/model/mongo/pom.xml
+++ b/model/mongo/pom.xml
@@ -46,17 +46,23 @@
             <artifactId>mongo-java-driver</artifactId>
             <scope>provided</scope>
         </dependency>
+
         <dependency>
-            <groupId>de.flapdoodle.embed</groupId>
-            <artifactId>de.flapdoodle.embed.mongo</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-model-tests</artifactId>
+            <version>${project.version}</version>
+            <classifier>tests</classifier>
             <scope>test</scope>
         </dependency>
     </dependencies>
+
+    <properties>
+        <keycloak.mongo.host>localhost</keycloak.mongo.host>
+        <keycloak.mongo.port>27018</keycloak.mongo.port>
+        <keycloak.mongo.db>keycloak</keycloak.mongo.db>
+        <keycloak.mongo.clearOnStartup>true</keycloak.mongo.clearOnStartup>
+    </properties>
+
     <build>
         <plugins>
             <plugin>
@@ -67,6 +73,66 @@
                     <target>1.6</target>
                 </configuration>
             </plugin>
+
+            <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>test</id>
+                        <phase>integration-test</phase>
+                        <goals>
+                            <goal>test</goal>
+                        </goals>
+                        <configuration>
+                            <systemPropertyVariables>
+                                <keycloak.mongo.host>${keycloak.mongo.host}</keycloak.mongo.host>
+                                <keycloak.mongo.port>${keycloak.mongo.port}</keycloak.mongo.port>
+                                <keycloak.mongo.db>${keycloak.mongo.db}</keycloak.mongo.db>
+                                <keycloak.mongo.clearOnStartup>${keycloak.mongo.clearOnStartup}</keycloak.mongo.clearOnStartup>
+                            </systemPropertyVariables>
+                            <dependenciesToScan>
+                                <dependency>org.keycloak:keycloak-model-tests</dependency>
+                            </dependenciesToScan>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>default-test</id>
+                        <configuration>
+                            <skip>true</skip>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!-- Embedded mongo -->
+            <plugin>
+                <groupId>com.github.joelittlejohn.embedmongo</groupId>
+                <artifactId>embedmongo-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>start-mongodb</id>
+                        <phase>pre-integration-test</phase>
+                        <goals>
+                            <goal>start</goal>
+                        </goals>
+                        <configuration>
+                            <port>${keycloak.mongo.port}</port>
+                            <logging>file</logging>
+                            <logFile>${project.build.directory}/mongodb.log</logFile>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>stop-mongodb</id>
+                        <phase>post-integration-test</phase>
+                        <goals>
+                            <goal>stop</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
         </plugins>
     </build>
 </project>
\ No newline at end of file
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/api/AbstractMongoIdentifiableEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/api/AbstractMongoIdentifiableEntity.java
index d6509e0..86e6e2e 100644
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/api/AbstractMongoIdentifiableEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/api/AbstractMongoIdentifiableEntity.java
@@ -18,7 +18,7 @@ public class AbstractMongoIdentifiableEntity implements MongoIdentifiableEntity 
     }
 
     @Override
-    public void afterRemove(MongoStore mongoStore, MongoStoreInvocationContext invocationContext) {
+    public void afterRemove(MongoStoreInvocationContext invocationContext) {
         // Empty by default
     }
 
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/api/context/MongoStoreInvocationContext.java b/model/mongo/src/main/java/org/keycloak/models/mongo/api/context/MongoStoreInvocationContext.java
index b6911e9..358f445 100644
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/api/context/MongoStoreInvocationContext.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/api/context/MongoStoreInvocationContext.java
@@ -1,12 +1,17 @@
 package org.keycloak.models.mongo.api.context;
 
 import org.keycloak.models.mongo.api.MongoIdentifiableEntity;
+import org.keycloak.models.mongo.api.MongoStore;
 
 /**
+ * Context, which provides callback methods to be invoked by MongoStore
+ *
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
 public interface MongoStoreInvocationContext {
 
+    void addCreatedObject(MongoIdentifiableEntity entity);
+
     void addLoadedObject(MongoIdentifiableEntity entity);
 
     <T extends MongoIdentifiableEntity> T getLoadedObject(Class<T> type, String id);
@@ -22,4 +27,6 @@ public interface MongoStoreInvocationContext {
     void commit();
 
     void rollback();
+
+    MongoStore getMongoStore();
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoIdentifiableEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoIdentifiableEntity.java
index 45ce126..dfa553e 100644
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoIdentifiableEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoIdentifiableEntity.java
@@ -17,5 +17,5 @@ public interface MongoIdentifiableEntity extends MongoEntity {
      * Lifecycle callback, which is called after removal of this object from Mongo.
      * It may be useful for triggering removal of wired objects.
      */
-    void afterRemove(MongoStore mongoStore, MongoStoreInvocationContext invocationContext);
+    void afterRemove(MongoStoreInvocationContext invocationContext);
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoStore.java b/model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoStore.java
index 1741149..9da25e5 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoStore.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/api/MongoStore.java
@@ -11,33 +11,33 @@ import java.util.List;
 public interface MongoStore {
 
     /**
-     * Insert new object
+     * Insert new entity
      *
-     * @param object to update
+     * @param entity to insert
      */
-    void insertObject(MongoIdentifiableEntity object, MongoStoreInvocationContext context);
+    void insertEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context);
 
     /**
-     * Update existing object
+     * Update existing entity
      *
-     * @param object to update
+     * @param entity to update
      */
-    void updateObject(MongoIdentifiableEntity object, MongoStoreInvocationContext context);
+    void updateEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context);
 
 
-    <T extends MongoIdentifiableEntity> T loadObject(Class<T> type, String oid, MongoStoreInvocationContext context);
+    <T extends MongoIdentifiableEntity> T loadEntity(Class<T> type, String id, MongoStoreInvocationContext context);
 
-    <T extends MongoIdentifiableEntity> T loadSingleObject(Class<T> type, DBObject query, MongoStoreInvocationContext context);
+    <T extends MongoIdentifiableEntity> T loadSingleEntity(Class<T> type, DBObject query, MongoStoreInvocationContext context);
 
-    <T extends MongoIdentifiableEntity> List<T> loadObjects(Class<T> type, DBObject query, MongoStoreInvocationContext context);
+    <T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context);
 
-    boolean removeObject(MongoIdentifiableEntity object, MongoStoreInvocationContext context);
+    boolean removeEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context);
 
-    boolean removeObject(Class<? extends MongoIdentifiableEntity> type, String id, MongoStoreInvocationContext context);
+    boolean removeEntity(Class<? extends MongoIdentifiableEntity> type, String id, MongoStoreInvocationContext context);
 
-    boolean removeObjects(Class<? extends MongoIdentifiableEntity> type, DBObject query, MongoStoreInvocationContext context);
+    boolean removeEntities(Class<? extends MongoIdentifiableEntity> type, DBObject query, MongoStoreInvocationContext context);
 
-    <S> boolean pushItemToList(MongoIdentifiableEntity object, String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent, MongoStoreInvocationContext context);
+    <S> boolean pushItemToList(MongoIdentifiableEntity entity, String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent, MongoStoreInvocationContext context);
 
-    <S> boolean pullItemFromList(MongoIdentifiableEntity object, String listPropertyName, S itemToPull, MongoStoreInvocationContext context);
+    <S> boolean pullItemFromList(MongoIdentifiableEntity entity, String listPropertyName, S itemToPull, MongoStoreInvocationContext context);
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/api/types/MapperRegistry.java b/model/mongo/src/main/java/org/keycloak/models/mongo/api/types/MapperRegistry.java
new file mode 100755
index 0000000..2c1c270
--- /dev/null
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/api/types/MapperRegistry.java
@@ -0,0 +1,111 @@
+package org.keycloak.models.mongo.api.types;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Registry of mappers, which allow to convert application object to database objects. MapperRegistry is main entry point to be used by application.
+ * Application can create instance of MapperRegistry and then register required Mapper objects.
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class MapperRegistry {
+
+    // TODO: Thread-safety support (maybe...)
+    // Mappers of Application objects to DB objects
+    private Map<Class<?>, Mapper<?, ?>> appObjectMappers = new HashMap<Class<?>, Mapper<?, ?>>();
+
+    // Mappers of DB objects to Application objects
+    private Map<Class<?>, Map<Class<?>, Mapper<?, ?>>> dbObjectMappers = new HashMap<Class<?>, Map<Class<?>, Mapper<?,?>>>();
+
+
+    /**
+     * Add mapper for converting application objects to DB objects
+     *
+     * @param mapper
+     */
+    public void addAppObjectMapper(Mapper<?, ?> mapper) {
+        appObjectMappers.put(mapper.getTypeOfObjectToConvert(), mapper);
+    }
+
+
+    /**
+     * Add mapper for converting DB objects to application objects
+     *
+     * @param mapper
+     */
+    public void addDBObjectMapper(Mapper<?, ?> mapper) {
+        Class<?> dbObjectType = mapper.getTypeOfObjectToConvert();
+        Class<?> appObjectType = mapper.getExpectedReturnType();
+        Map<Class<?>, Mapper<?, ?>> appObjects = dbObjectMappers.get(dbObjectType);
+        if (appObjects == null) {
+            appObjects = new HashMap<Class<?>, Mapper<?, ?>>();
+            dbObjectMappers.put(dbObjectType, appObjects);
+        }
+        appObjects.put(appObjectType, mapper);
+    }
+
+
+    public <S> S convertDBObjectToApplicationObject(MapperContext<Object, S> context) {
+        Object dbObject = context.getObjectToConvert();
+        Class<?> expectedApplicationObjectType = context.getExpectedReturnType();
+
+        Class<?> dbObjectType = dbObject.getClass();
+        Mapper<Object, S> mapper;
+
+        Map<Class<?>, Mapper<?, ?>> appObjects = dbObjectMappers.get(dbObjectType);
+        if (appObjects == null) {
+            throw new IllegalArgumentException("Not found any mappers for type " + dbObjectType);
+        } else {
+            if (appObjects.size() == 1) {
+                mapper = (Mapper<Object, S>)appObjects.values().iterator().next();
+            } else {
+                // Try to find converter for requested application type
+                mapper = (Mapper<Object, S>)getAppConverterForType(context.getExpectedReturnType(), appObjects);
+            }
+        }
+
+        if (mapper == null) {
+            throw new IllegalArgumentException("Can't found mapper for type " + dbObjectType + " and expectedApplicationType " + expectedApplicationObjectType);
+        }
+
+        return mapper.convertObject(context);
+    }
+
+
+    public <S> S convertApplicationObjectToDBObject(Object applicationObject, Class<S> expectedDBObjectType) {
+        Class<?> appObjectType = applicationObject.getClass();
+        Mapper<Object, S> mapper = (Mapper<Object, S>)getAppConverterForType(appObjectType, appObjectMappers);
+        if (mapper == null) {
+            throw new IllegalArgumentException("Can't found converter for type " + appObjectType + " in registered appObjectMappers");
+        }
+        if (!expectedDBObjectType.isAssignableFrom(mapper.getExpectedReturnType())) {
+            throw new IllegalArgumentException("Converter " + mapper + " has return type " + mapper.getExpectedReturnType() +
+                    " but we need type " + expectedDBObjectType);
+        }
+        return mapper.convertObject(new MapperContext(applicationObject, expectedDBObjectType, null));
+    }
+
+    // Try to find converter for given type or all it's supertypes
+    private static Mapper<Object, ?> getAppConverterForType(Class<?> appObjectType, Map<Class<?>, Mapper<?, ?>> appObjectConverters) {
+        Mapper<Object, ?> mapper = (Mapper<Object, ?>)appObjectConverters.get(appObjectType);
+        if (mapper != null) {
+            return mapper;
+        } else {
+            Class<?>[] interfaces = appObjectType.getInterfaces();
+            for (Class<?> interface1 : interfaces) {
+                mapper = getAppConverterForType(interface1, appObjectConverters);
+                if (mapper != null) {
+                    return mapper;
+                }
+            }
+
+            Class<?> superType = appObjectType.getSuperclass();
+            if (superType != null) {
+                return getAppConverterForType(superType, appObjectConverters);
+            } else {
+                return null;
+            }
+        }
+    }
+}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/impl/context/SimpleMongoStoreInvocationContext.java b/model/mongo/src/main/java/org/keycloak/models/mongo/impl/context/SimpleMongoStoreInvocationContext.java
index 18c2d6a..b0c871d 100644
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/impl/context/SimpleMongoStoreInvocationContext.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/impl/context/SimpleMongoStoreInvocationContext.java
@@ -13,10 +13,14 @@ import org.keycloak.models.mongo.api.context.MongoTask;
  */
 public class SimpleMongoStoreInvocationContext implements MongoStoreInvocationContext {
 
-    private final MongoStore store;
+    private final MongoStore mongoStore;
 
-    public SimpleMongoStoreInvocationContext(MongoStore store) {
-        this.store = store;
+    public SimpleMongoStoreInvocationContext(MongoStore mongoStore) {
+        this.mongoStore = mongoStore;
+    }
+
+    @Override
+    public void addCreatedObject(MongoIdentifiableEntity entity) {
     }
 
     @Override
@@ -35,7 +39,7 @@ public class SimpleMongoStoreInvocationContext implements MongoStoreInvocationCo
 
     @Override
     public void addRemovedObject(MongoIdentifiableEntity entityToRemove) {
-        entityToRemove.afterRemove(store, this);
+        entityToRemove.afterRemove(this);
     }
 
     @Override
@@ -53,4 +57,9 @@ public class SimpleMongoStoreInvocationContext implements MongoStoreInvocationCo
     @Override
     public void rollback() {
     }
+
+    @Override
+    public MongoStore getMongoStore() {
+        return mongoStore;
+    }
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/impl/context/TransactionMongoStoreInvocationContext.java b/model/mongo/src/main/java/org/keycloak/models/mongo/impl/context/TransactionMongoStoreInvocationContext.java
index 1f9f66d..5d5ff08 100644
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/impl/context/TransactionMongoStoreInvocationContext.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/impl/context/TransactionMongoStoreInvocationContext.java
@@ -2,6 +2,7 @@ package org.keycloak.models.mongo.impl.context;
 
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
 
@@ -32,6 +33,12 @@ public class TransactionMongoStoreInvocationContext implements MongoStoreInvocat
     }
 
     @Override
+    public void addCreatedObject(MongoIdentifiableEntity entity) {
+        // For now just add it to list of loaded objects
+        addLoadedObject(entity);
+    }
+
+    @Override
     public void addLoadedObject(MongoIdentifiableEntity entity) {
         loadedObjects.put(entity.getId(), entity);
     }
@@ -49,7 +56,7 @@ public class TransactionMongoStoreInvocationContext implements MongoStoreInvocat
 
         Set<MongoTask> currentObjectTasks = pendingUpdateTasks.get(entityToUpdate);
         if (currentObjectTasks == null) {
-            currentObjectTasks = new HashSet<MongoTask>();
+            currentObjectTasks = new LinkedHashSet<MongoTask>();
             pendingUpdateTasks.put(entityToUpdate, currentObjectTasks);
         } else {
             // if task is full update, then remove all other tasks as we need to do full update of object anyway
@@ -74,7 +81,7 @@ public class TransactionMongoStoreInvocationContext implements MongoStoreInvocat
         pendingUpdateTasks.remove(entityToRemove);
         loadedObjects.remove(entityToRemove.getId());
 
-        entityToRemove.afterRemove(mongoStore, this);
+        entityToRemove.afterRemove(this);
     }
 
     @Override
@@ -107,8 +114,6 @@ public class TransactionMongoStoreInvocationContext implements MongoStoreInvocat
 
     @Override
     public void commit() {
-        loadedObjects.clear();
-
         // Now execute all pending update tasks
         for (Set<MongoTask> mongoTasks : pendingUpdateTasks.values()) {
             for (MongoTask currentTask : mongoTasks) {
@@ -117,13 +122,19 @@ public class TransactionMongoStoreInvocationContext implements MongoStoreInvocat
         }
 
         // And clear it
+        loadedObjects.clear();
         pendingUpdateTasks.clear();
     }
 
     @Override
     public void rollback() {
-        // Just clear the map without executions of tasks
+        // Just clear the map without executions of tasks TODO: Attempt to do complete rollback (removal of created objects, restoring of removed objects, rollback of updates)
         loadedObjects.clear();
         pendingUpdateTasks.clear();
     }
+
+    @Override
+    public MongoStore getMongoStore() {
+        return mongoStore;
+    }
 }
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 5fe1d0a..0bbc094 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
@@ -15,18 +15,18 @@ import org.keycloak.models.mongo.api.MongoIdentifiableEntity;
 import org.keycloak.models.mongo.api.MongoStore;
 import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
 import org.keycloak.models.mongo.api.context.MongoTask;
-import org.keycloak.models.mongo.api.types.Converter;
-import org.keycloak.models.mongo.api.types.ConverterContext;
-import org.keycloak.models.mongo.api.types.TypeConverter;
-import org.keycloak.models.mongo.impl.types.BasicDBListConverter;
-import org.keycloak.models.mongo.impl.types.BasicDBObjectConverter;
-import org.keycloak.models.mongo.impl.types.BasicDBObjectToMapConverter;
-import org.keycloak.models.mongo.impl.types.EnumToStringConverter;
-import org.keycloak.models.mongo.impl.types.ListConverter;
-import org.keycloak.models.mongo.impl.types.MapConverter;
-import org.keycloak.models.mongo.impl.types.MongoEntityConverter;
-import org.keycloak.models.mongo.impl.types.SimpleConverter;
-import org.keycloak.models.mongo.impl.types.StringToEnumConverter;
+import org.keycloak.models.mongo.api.types.Mapper;
+import org.keycloak.models.mongo.api.types.MapperContext;
+import org.keycloak.models.mongo.api.types.MapperRegistry;
+import org.keycloak.models.mongo.impl.types.BasicDBListMapper;
+import org.keycloak.models.mongo.impl.types.BasicDBObjectMapper;
+import org.keycloak.models.mongo.impl.types.BasicDBObjectToMapMapper;
+import org.keycloak.models.mongo.impl.types.EnumToStringMapper;
+import org.keycloak.models.mongo.impl.types.ListMapper;
+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.picketlink.common.properties.Property;
 import org.picketlink.common.properties.query.AnnotatedPropertyCriteria;
 import org.picketlink.common.properties.query.PropertyQueries;
@@ -49,39 +49,39 @@ public class MongoStoreImpl implements MongoStore {
     private final DB database;
     private static final Logger logger = Logger.getLogger(MongoStoreImpl.class);
 
-    private final TypeConverter typeConverter;
-    private ConcurrentMap<Class<? extends MongoEntity>, ObjectInfo> objectInfoCache =
-            new ConcurrentHashMap<Class<? extends MongoEntity>, ObjectInfo>();
+    private final MapperRegistry mapperRegistry;
+    private ConcurrentMap<Class<? extends MongoEntity>, EntityInfo> entityInfoCache =
+            new ConcurrentHashMap<Class<? extends MongoEntity>, EntityInfo>();
 
 
     public MongoStoreImpl(DB database, boolean clearCollectionsOnStartup, Class<? extends MongoEntity>[] managedEntityTypes) {
         this.database = database;
 
-        typeConverter = new TypeConverter();
+        mapperRegistry = new MapperRegistry();
 
         for (Class<?> simpleConverterClass : SIMPLE_TYPES) {
-            SimpleConverter converter = new SimpleConverter(simpleConverterClass);
-            typeConverter.addAppObjectConverter(converter);
-            typeConverter.addDBObjectConverter(converter);
+            SimpleMapper converter = new SimpleMapper(simpleConverterClass);
+            mapperRegistry.addAppObjectMapper(converter);
+            mapperRegistry.addDBObjectMapper(converter);
         }
 
         // Specific converter for ArrayList is added just for performance purposes to avoid recursive converter lookup (most of list impl will be ArrayList)
-        typeConverter.addAppObjectConverter(new ListConverter(typeConverter, ArrayList.class));
-        typeConverter.addAppObjectConverter(new ListConverter(typeConverter, List.class));
-        typeConverter.addDBObjectConverter(new BasicDBListConverter(typeConverter));
+        mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, ArrayList.class));
+        mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, List.class));
+        mapperRegistry.addDBObjectMapper(new BasicDBListMapper(mapperRegistry));
 
-        typeConverter.addAppObjectConverter(new MapConverter(HashMap.class));
-        typeConverter.addAppObjectConverter(new MapConverter(Map.class));
-        typeConverter.addDBObjectConverter(new BasicDBObjectToMapConverter());
+        mapperRegistry.addAppObjectMapper(new MapMapper(HashMap.class));
+        mapperRegistry.addAppObjectMapper(new MapMapper(Map.class));
+        mapperRegistry.addDBObjectMapper(new BasicDBObjectToMapMapper());
 
         // Enum converters
-        typeConverter.addAppObjectConverter(new EnumToStringConverter());
-        typeConverter.addDBObjectConverter(new StringToEnumConverter());
+        mapperRegistry.addAppObjectMapper(new EnumToStringMapper());
+        mapperRegistry.addDBObjectMapper(new StringToEnumMapper());
 
         for (Class<? extends MongoEntity> type : managedEntityTypes) {
-            getObjectInfo(type);
-            typeConverter.addAppObjectConverter(new MongoEntityConverter(this, typeConverter, type));
-            typeConverter.addDBObjectConverter(new BasicDBObjectConverter(this, typeConverter, type));
+            getEntityInfo(type);
+            mapperRegistry.addAppObjectMapper(new MongoEntityMapper(this, mapperRegistry, type));
+            mapperRegistry.addDBObjectMapper(new BasicDBObjectMapper(this, mapperRegistry, type));
         }
 
         if (clearCollectionsOnStartup) {
@@ -107,18 +107,18 @@ public class MongoStoreImpl implements MongoStore {
     }
 
     @Override
-    public void insertObject(MongoIdentifiableEntity object, MongoStoreInvocationContext context) {
-        Class<? extends MongoEntity> clazz = object.getClass();
+    public void insertEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
+        Class<? extends MongoEntity> clazz = entity.getClass();
 
         // Find annotations for ID, for all the properties and for the name of the collection.
-        ObjectInfo objectInfo = getObjectInfo(clazz);
+        EntityInfo entityInfo = getEntityInfo(clazz);
 
         // Create instance of BasicDBObject and add all declared properties to it (properties with null value probably should be skipped)
-        BasicDBObject dbObject = typeConverter.convertApplicationObjectToDBObject(object, BasicDBObject.class);
+        BasicDBObject dbObject = mapperRegistry.convertApplicationObjectToDBObject(entity, BasicDBObject.class);
 
-        DBCollection dbCollection = database.getCollection(objectInfo.getDbCollectionName());
+        DBCollection dbCollection = database.getCollection(entityInfo.getDbCollectionName());
 
-        String currentId = object.getId();
+        String currentId = entity.getId();
 
         // Inserting object, which already has oid property set. So we need to set "_id"
         if (currentId != null) {
@@ -129,28 +129,28 @@ public class MongoStoreImpl implements MongoStore {
 
         // Add id to value of given object
         if (currentId == null) {
-            object.setId(dbObject.getString("_id"));
+            entity.setId(dbObject.getString("_id"));
         }
 
         // Treat object as if it is read (It is already submited to transaction)
-        context.addLoadedObject(object);
+        context.addLoadedObject(entity);
     }
 
     @Override
-    public void updateObject(final MongoIdentifiableEntity object, MongoStoreInvocationContext context) {
+    public void updateEntity(final MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
         MongoTask fullUpdateTask = new MongoTask() {
 
             @Override
             public void execute() {
-                Class<? extends MongoEntity> clazz = object.getClass();
-                ObjectInfo objectInfo = getObjectInfo(clazz);
-                BasicDBObject dbObject = typeConverter.convertApplicationObjectToDBObject(object, BasicDBObject.class);
-                DBCollection dbCollection = database.getCollection(objectInfo.getDbCollectionName());
+                Class<? extends MongoEntity> clazz = entity.getClass();
+                EntityInfo entityInfo = getEntityInfo(clazz);
+                BasicDBObject dbObject = mapperRegistry.convertApplicationObjectToDBObject(entity, BasicDBObject.class);
+                DBCollection dbCollection = database.getCollection(entityInfo.getDbCollectionName());
 
-                String currentId = object.getId();
+                String currentId = entity.getId();
 
                 if (currentId == null) {
-                    throw new IllegalStateException("Can't update object without id: " + object);
+                    throw new IllegalStateException("Can't update entity without id: " + entity);
                 } else {
                     BasicDBObject query = new BasicDBObject("_id", getObjectId(currentId));
                     dbCollection.update(query, dbObject);
@@ -164,12 +164,12 @@ public class MongoStoreImpl implements MongoStore {
         };
 
         // update is just added to context and postponed
-        context.addUpdateTask(object, fullUpdateTask);
+        context.addUpdateTask(entity, fullUpdateTask);
     }
 
 
     @Override
-    public <T extends MongoIdentifiableEntity> T loadObject(Class<T> type, String id, MongoStoreInvocationContext context) {
+    public <T extends MongoIdentifiableEntity> T loadEntity(Class<T> type, String id, MongoStoreInvocationContext context) {
         // First look if we already read the object with this oid and type during this transaction. If yes, use it instead of DB lookup
         T cached = context.getLoadedObject(type, id);
         if (cached != null) return cached;
@@ -181,8 +181,8 @@ public class MongoStoreImpl implements MongoStore {
 
         if (dbObject == null) return null;
 
-        ConverterContext<Object> converterContext = new ConverterContext<Object>(dbObject, type, null);
-        T converted = (T)typeConverter.convertDBObjectToApplicationObject(converterContext);
+        MapperContext<Object, T> mapperContext = new MapperContext<Object, T>(dbObject, type, null);
+        T converted = mapperRegistry.convertDBObjectToApplicationObject(mapperContext);
 
         // Now add it to loaded objects
         context.addLoadedObject(converted);
@@ -192,8 +192,8 @@ public class MongoStoreImpl implements MongoStore {
 
 
     @Override
-    public <T extends MongoIdentifiableEntity> T loadSingleObject(Class<T> type, DBObject query, MongoStoreInvocationContext context) {
-        List<T> result = loadObjects(type, query, context);
+    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) {
@@ -206,7 +206,7 @@ public class MongoStoreImpl implements MongoStore {
 
 
     @Override
-    public <T extends MongoIdentifiableEntity> List<T> loadObjects(Class<T> type, DBObject query, MongoStoreInvocationContext context) {
+    public <T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context) {
         // First we should execute all pending tasks before searching DB
         context.beforeDBSearch(type);
 
@@ -218,21 +218,21 @@ public class MongoStoreImpl implements MongoStore {
 
 
     @Override
-    public boolean removeObject(MongoIdentifiableEntity object, MongoStoreInvocationContext context) {
-        return removeObject(object.getClass(), object.getId(), context);
+    public boolean removeEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
+        return removeEntity(entity.getClass(), entity.getId(), context);
     }
 
 
     @Override
-    public boolean removeObject(Class<? extends MongoIdentifiableEntity> type, String id, MongoStoreInvocationContext context) {
-        MongoIdentifiableEntity found = loadObject(type, id, context);
+    public boolean removeEntity(Class<? extends MongoIdentifiableEntity> type, String id, MongoStoreInvocationContext context) {
+        MongoIdentifiableEntity found = loadEntity(type, id, context);
         if (found == null) {
             return false;
         } else {
             DBCollection dbCollection = getDBCollectionForType(type);
             BasicDBObject dbQuery = new BasicDBObject("_id", getObjectId(id));
             dbCollection.remove(dbQuery);
-            logger.info("Object of type: " + type + ", id: " + id + " removed from MongoDB.");
+            logger.info("Entity of type: " + type + ", id: " + id + " removed from MongoDB.");
 
             context.addRemovedObject(found);
             return true;
@@ -241,14 +241,14 @@ public class MongoStoreImpl implements MongoStore {
 
 
     @Override
-    public boolean removeObjects(Class<? extends MongoIdentifiableEntity> type, DBObject query, MongoStoreInvocationContext context) {
-        List<? extends MongoIdentifiableEntity> foundObjects = loadObjects(type, query, context);
+    public boolean removeEntities(Class<? extends MongoIdentifiableEntity> type, DBObject query, MongoStoreInvocationContext context) {
+        List<? extends MongoIdentifiableEntity> foundObjects = loadEntities(type, query, context);
         if (foundObjects.size() == 0) {
             return false;
         } else {
             DBCollection dbCollection = getDBCollectionForType(type);
             dbCollection.remove(query);
-            logger.info("Removed " + foundObjects.size() + " objects of type: " + type + ", query: " + query);
+            logger.info("Removed " + foundObjects.size() + " entities of type: " + type + ", query: " + query);
 
             for (MongoIdentifiableEntity found : foundObjects) {
                 context.addRemovedObject(found);;
@@ -258,20 +258,20 @@ public class MongoStoreImpl implements MongoStore {
     }
 
     @Override
-    public <S> boolean pushItemToList(final MongoIdentifiableEntity object, final String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent, MongoStoreInvocationContext context) {
-        final Class<? extends MongoEntity> type = object.getClass();
-        ObjectInfo objectInfo = getObjectInfo(type);
+    public <S> boolean pushItemToList(final MongoIdentifiableEntity entity, final String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent, MongoStoreInvocationContext context) {
+        final Class<? extends MongoEntity> type = entity.getClass();
+        EntityInfo entityInfo = getEntityInfo(type);
 
         // Add item to list directly in this object
-        Property<Object> listProperty = objectInfo.getPropertyByName(listPropertyName);
+        Property<Object> listProperty = entityInfo.getPropertyByName(listPropertyName);
         if (listProperty == null) {
-            throw new IllegalArgumentException("Property " + listPropertyName + " doesn't exist on object " + object);
+            throw new IllegalArgumentException("Property " + listPropertyName + " doesn't exist on object " + entity);
         }
 
-        List<S> list = (List<S>)listProperty.getValue(object);
+        List<S> list = (List<S>)listProperty.getValue(entity);
         if (list == null) {
             list = new ArrayList<S>();
-            listProperty.setValue(object, list);
+            listProperty.setValue(entity, list);
         }
 
         // Skip if item is already in list
@@ -284,14 +284,14 @@ public class MongoStoreImpl implements MongoStore {
 
         // Add update of list to pending tasks
         final List<S> listt = list;
-        context.addUpdateTask(object, new MongoTask() {
+        context.addUpdateTask(entity, new MongoTask() {
 
             @Override
             public void execute() {
                 // Now DB update of new list with usage of $set
-                BasicDBList dbList = typeConverter.convertApplicationObjectToDBObject(listt, BasicDBList.class);
+                BasicDBList dbList = mapperRegistry.convertApplicationObjectToDBObject(listt, BasicDBList.class);
 
-                BasicDBObject query = new BasicDBObject("_id", getObjectId(object.getId()));
+                BasicDBObject query = new BasicDBObject("_id", getObjectId(entity.getId()));
                 BasicDBObject listObject = new BasicDBObject(listPropertyName, dbList);
                 BasicDBObject setCommand = new BasicDBObject("$set", listObject);
                 getDBCollectionForType(type).update(query, setCommand);
@@ -308,16 +308,16 @@ public class MongoStoreImpl implements MongoStore {
 
 
     @Override
-    public <S> boolean pullItemFromList(final MongoIdentifiableEntity object, final String listPropertyName, final S itemToPull, MongoStoreInvocationContext context) {
-        final Class<? extends MongoEntity> type = object.getClass();
-        ObjectInfo objectInfo = getObjectInfo(type);
+    public <S> boolean pullItemFromList(final MongoIdentifiableEntity entity, final String listPropertyName, final S itemToPull, MongoStoreInvocationContext context) {
+        final Class<? extends MongoEntity> type = entity.getClass();
+        EntityInfo entityInfo = getEntityInfo(type);
 
         // Remove item from list directly in this object
-        Property<Object> listProperty = objectInfo.getPropertyByName(listPropertyName);
+        Property<Object> listProperty = entityInfo.getPropertyByName(listPropertyName);
         if (listProperty == null) {
-            throw new IllegalArgumentException("Property " + listPropertyName + " doesn't exist on object " + object);
+            throw new IllegalArgumentException("Property " + listPropertyName + " doesn't exist on object " + entity);
         }
-        List<S> list = (List<S>)listProperty.getValue(object);
+        List<S> list = (List<S>)listProperty.getValue(entity);
 
         // If list is null, we skip both object and DB update
         if (list == null || !list.contains(itemToPull)) {
@@ -328,13 +328,13 @@ public class MongoStoreImpl implements MongoStore {
             list.remove(itemToPull);
 
             // Add update of list to pending tasks
-            context.addUpdateTask(object, new MongoTask() {
+            context.addUpdateTask(entity, new MongoTask() {
 
                 @Override
                 public void execute() {
                     // Pull item from DB
-                    Object dbItemToPull = typeConverter.convertApplicationObjectToDBObject(itemToPull, Object.class);
-                    BasicDBObject query = new BasicDBObject("_id", getObjectId(object.getId()));
+                    Object dbItemToPull = mapperRegistry.convertApplicationObjectToDBObject(itemToPull, Object.class);
+                    BasicDBObject query = new BasicDBObject("_id", getObjectId(entity.getId()));
                     BasicDBObject pullObject = new BasicDBObject(listPropertyName, dbItemToPull);
                     BasicDBObject pullCommand = new BasicDBObject("$pull", pullObject);
                     getDBCollectionForType(type).update(query, pullCommand);
@@ -351,31 +351,31 @@ public class MongoStoreImpl implements MongoStore {
     }
 
     // Possibility to add user-defined converters
-    public void addAppObjectConverter(Converter<?, ?> converter) {
-        typeConverter.addAppObjectConverter(converter);
+    public void addAppObjectConverter(Mapper<?, ?> mapper) {
+        mapperRegistry.addAppObjectMapper(mapper);
     }
 
-    public void addDBObjectConverter(Converter<?, ?> converter) {
-        typeConverter.addDBObjectConverter(converter);
+    public void addDBObjectConverter(Mapper<?, ?> mapper) {
+        mapperRegistry.addDBObjectMapper(mapper);
     }
 
-    public ObjectInfo getObjectInfo(Class<? extends MongoEntity> objectClass) {
-        ObjectInfo objectInfo = objectInfoCache.get(objectClass);
-        if (objectInfo == null) {
+    public EntityInfo getEntityInfo(Class<? extends MongoEntity> objectClass) {
+        EntityInfo entityInfo = entityInfoCache.get(objectClass);
+        if (entityInfo == null) {
             List<Property<Object>> properties = PropertyQueries.createQuery(objectClass).addCriteria(new AnnotatedPropertyCriteria(MongoField.class)).getResultList();
 
             MongoCollection classAnnotation = objectClass.getAnnotation(MongoCollection.class);
 
             String dbCollectionName = classAnnotation==null ? null : classAnnotation.collectionName();
-            objectInfo = new ObjectInfo(objectClass, dbCollectionName, properties);
+            entityInfo = new EntityInfo(objectClass, dbCollectionName, properties);
 
-            ObjectInfo existing = objectInfoCache.putIfAbsent(objectClass, objectInfo);
+            EntityInfo existing = entityInfoCache.putIfAbsent(objectClass, entityInfo);
             if (existing != null) {
-                objectInfo = existing;
+                entityInfo = existing;
             }
         }
 
-        return objectInfo;
+        return entityInfo;
     }
 
     protected <T extends MongoIdentifiableEntity> List<T> convertCursor(Class<T> type, DBCursor cursor, MongoStoreInvocationContext context) {
@@ -389,8 +389,8 @@ public class MongoStoreImpl implements MongoStore {
 
                 if (object == null) {
                     // So convert and use fresh instance from DB
-                    ConverterContext<Object> converterContext = new ConverterContext<Object>(dbObject, type, null);
-                    object = (T)typeConverter.convertDBObjectToApplicationObject(converterContext);
+                    MapperContext<Object, T> mapperContext = new MapperContext<Object, T>(dbObject, type, null);
+                    object = mapperRegistry.convertDBObjectToApplicationObject(mapperContext);
                     context.addLoadedObject(object);
                 }
 
@@ -404,9 +404,9 @@ public class MongoStoreImpl implements MongoStore {
     }
 
     protected DBCollection getDBCollectionForType(Class<? extends MongoEntity> type) {
-        ObjectInfo objectInfo = getObjectInfo(type);
-        String dbCollectionName = objectInfo.getDbCollectionName();
-        return dbCollectionName==null ? null : database.getCollection(objectInfo.getDbCollectionName());
+        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".
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/AbstractAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/AbstractAdapter.java
index cd6a1dd..9e4f945 100644
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/AbstractAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/AbstractAdapter.java
@@ -9,11 +9,9 @@ import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
  */
 public abstract class AbstractAdapter {
 
-    protected MongoStore mongoStore;
     protected MongoStoreInvocationContext invocationContext;
 
-    public AbstractAdapter(MongoStore mongoStore, MongoStoreInvocationContext invocationContext) {
-        this.mongoStore = mongoStore;
+    public AbstractAdapter(MongoStoreInvocationContext invocationContext) {
         this.invocationContext = invocationContext;
     }
 
@@ -35,4 +33,8 @@ public abstract class AbstractAdapter {
     public int hashCode() {
         return getMongoEntity()!=null ? getMongoEntity().hashCode() : super.hashCode();
     }
+
+    protected MongoStore getMongoStore() {
+        return invocationContext.getMongoStore();
+    }
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java
index e4ca675..0686f42 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java
@@ -6,7 +6,6 @@ import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
-import org.keycloak.models.mongo.api.MongoStore;
 import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
 import org.keycloak.models.mongo.keycloak.entities.ApplicationEntity;
 import org.keycloak.models.mongo.keycloak.entities.RoleEntity;
@@ -26,30 +25,30 @@ public class ApplicationAdapter extends AbstractAdapter implements ApplicationMo
     private final ApplicationEntity application;
     private UserAdapter resourceUser;
 
-    public ApplicationAdapter(ApplicationEntity applicationEntity, MongoStore mongoStore, MongoStoreInvocationContext invContext) {
-        this(applicationEntity, null, mongoStore, invContext);
+    public ApplicationAdapter(ApplicationEntity applicationEntity, MongoStoreInvocationContext invContext) {
+        this(applicationEntity, null, invContext);
     }
 
-    public ApplicationAdapter(ApplicationEntity applicationEntity, UserAdapter resourceUser, MongoStore mongoStore, MongoStoreInvocationContext invContext) {
-        super(mongoStore, invContext);
+    public ApplicationAdapter(ApplicationEntity applicationEntity, UserAdapter resourceUser, MongoStoreInvocationContext invContext) {
+        super(invContext);
         this.application = applicationEntity;
         this.resourceUser = resourceUser;
     }
 
     @Override
     public void updateApplication() {
-        mongoStore.updateObject(application, invocationContext);
+        getMongoStore().updateEntity(application, invocationContext);
     }
 
     @Override
     public UserAdapter getApplicationUser() {
         // This is not thread-safe. Assumption is that ApplicationAdapter instance is per-client object
         if (resourceUser == null) {
-            UserEntity userEntity = mongoStore.loadObject(UserEntity.class, application.getResourceUserId(), invocationContext);
+            UserEntity userEntity = getMongoStore().loadEntity(UserEntity.class, application.getResourceUserId(), invocationContext);
             if (userEntity == null) {
                 throw new IllegalStateException("User " + application.getResourceUserId() + " not found");
             }
-            resourceUser = new UserAdapter(userEntity, mongoStore, invocationContext);
+            resourceUser = new UserAdapter(userEntity, invocationContext);
         }
 
         return resourceUser;
@@ -116,21 +115,21 @@ public class ApplicationAdapter extends AbstractAdapter implements ApplicationMo
                 .and("name").is(name)
                 .and("applicationId").is(getId())
                 .get();
-        RoleEntity role = mongoStore.loadSingleObject(RoleEntity.class, query, invocationContext);
+        RoleEntity role = getMongoStore().loadSingleEntity(RoleEntity.class, query, invocationContext);
         if (role == null) {
             return null;
         } else {
-            return new RoleAdapter(role, this, mongoStore, invocationContext);
+            return new RoleAdapter(role, invocationContext);
         }
     }
 
     @Override
     public RoleModel getRoleById(String id) {
-        RoleEntity role = mongoStore.loadObject(RoleEntity.class, id, invocationContext);
+        RoleEntity role = getMongoStore().loadEntity(RoleEntity.class, id, invocationContext);
         if (role == null) {
             return null;
         } else {
-            return new RoleAdapter(role, this, mongoStore, invocationContext);
+            return new RoleAdapter(role, this, invocationContext);
         }
     }
 
@@ -145,13 +144,13 @@ public class ApplicationAdapter extends AbstractAdapter implements ApplicationMo
         roleEntity.setName(name);
         roleEntity.setApplicationId(getId());
 
-        mongoStore.insertObject(roleEntity, invocationContext);
-        return new RoleAdapter(roleEntity, this, mongoStore, invocationContext);
+        getMongoStore().insertEntity(roleEntity, invocationContext);
+        return new RoleAdapter(roleEntity, this, invocationContext);
     }
 
     @Override
     public boolean removeRoleById(String id) {
-        return mongoStore.removeObject(RoleEntity.class ,id, invocationContext);
+        return getMongoStore().removeEntity(RoleEntity.class, id, invocationContext);
     }
 
     @Override
@@ -159,11 +158,11 @@ public class ApplicationAdapter extends AbstractAdapter implements ApplicationMo
         DBObject query = new QueryBuilder()
                 .and("applicationId").is(getId())
                 .get();
-        List<RoleEntity> roles = mongoStore.loadObjects(RoleEntity.class, query, invocationContext);
+        List<RoleEntity> roles = getMongoStore().loadEntities(RoleEntity.class, query, invocationContext);
 
         Set<RoleModel> result = new HashSet<RoleModel>();
         for (RoleEntity role : roles) {
-            result.add(new RoleAdapter(role, this, mongoStore, invocationContext));
+            result.add(new RoleAdapter(role, this, invocationContext));
         }
 
         return result;
@@ -172,11 +171,11 @@ public class ApplicationAdapter extends AbstractAdapter implements ApplicationMo
     @Override
     public Set<RoleModel> getApplicationRoleMappings(UserModel user) {
         Set<RoleModel> result = new HashSet<RoleModel>();
-        List<RoleEntity> roles = MongoModelUtils.getAllRolesOfUser(user, mongoStore, invocationContext);
+        List<RoleEntity> roles = MongoModelUtils.getAllRolesOfUser(user, invocationContext);
 
         for (RoleEntity role : roles) {
             if (getId().equals(role.getApplicationId())) {
-                result.add(new RoleAdapter(role, this, mongoStore, invocationContext));
+                result.add(new RoleAdapter(role, this, invocationContext));
             }
         }
         return result;
@@ -185,17 +184,17 @@ public class ApplicationAdapter extends AbstractAdapter implements ApplicationMo
     @Override
     public void addScope(RoleModel role) {
         UserAdapter appUser = getApplicationUser();
-        mongoStore.pushItemToList(appUser.getUser(), "scopeIds", role.getId(), true, invocationContext);
+        getMongoStore().pushItemToList(appUser.getUser(), "scopeIds", role.getId(), true, invocationContext);
     }
 
     @Override
     public Set<RoleModel> getApplicationScopeMappings(UserModel user) {
         Set<RoleModel> result = new HashSet<RoleModel>();
-        List<RoleEntity> roles = MongoModelUtils.getAllScopesOfUser(user, mongoStore, invocationContext);
+        List<RoleEntity> roles = MongoModelUtils.getAllScopesOfUser(user, invocationContext);
 
         for (RoleEntity role : roles) {
             if (getId().equals(role.getApplicationId())) {
-                result.add(new RoleAdapter(role, this, mongoStore, invocationContext));
+                result.add(new RoleAdapter(role, this, invocationContext));
             }
         }
         return result;
@@ -213,7 +212,7 @@ public class ApplicationAdapter extends AbstractAdapter implements ApplicationMo
             addRole(name);
         }
 
-        mongoStore.pushItemToList(application, "defaultRoles", name, true, invocationContext);
+        getMongoStore().pushItemToList(application, "defaultRoles", name, true, invocationContext);
     }
 
     @Override
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSession.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSession.java
index e612a54..a57916b 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSession.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSession.java
@@ -9,7 +9,6 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.mongo.api.MongoStore;
 import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.models.mongo.impl.context.SimpleMongoStoreInvocationContext;
 import org.keycloak.models.mongo.impl.context.TransactionMongoStoreInvocationContext;
 import org.keycloak.models.mongo.keycloak.entities.RealmEntity;
 import org.keycloak.models.utils.KeycloakModelUtils;
@@ -24,10 +23,8 @@ public class MongoKeycloakSession implements KeycloakSession {
 
     private final MongoStoreInvocationContext invocationContext;
     private final MongoKeycloakTransaction transaction;
-    private final MongoStore mongoStore;
 
     public MongoKeycloakSession(MongoStore mongoStore) {
-        this.mongoStore = mongoStore;
         // this.invocationContext = new SimpleMongoStoreInvocationContext(mongoStore);
         this.invocationContext = new TransactionMongoStoreInvocationContext(mongoStore);
         this.transaction = new MongoKeycloakTransaction(invocationContext);
@@ -58,25 +55,25 @@ public class MongoKeycloakSession implements KeycloakSession {
         newRealm.setId(id);
         newRealm.setName(name);
 
-        mongoStore.insertObject(newRealm, invocationContext);
+        getMongoStore().insertEntity(newRealm, invocationContext);
 
-        return new RealmAdapter(newRealm, mongoStore, invocationContext);
+        return new RealmAdapter(newRealm, invocationContext);
     }
 
     @Override
     public RealmModel getRealm(String id) {
-        RealmEntity realmEntity = mongoStore.loadObject(RealmEntity.class, id, invocationContext);
-        return realmEntity != null ? new RealmAdapter(realmEntity, mongoStore, invocationContext) : null;
+        RealmEntity realmEntity = getMongoStore().loadEntity(RealmEntity.class, id, invocationContext);
+        return realmEntity != null ? new RealmAdapter(realmEntity, invocationContext) : null;
     }
 
     @Override
     public List<RealmModel> getRealms(UserModel admin) {
         DBObject query = new BasicDBObject();
-        List<RealmEntity> realms = mongoStore.loadObjects(RealmEntity.class, query, invocationContext);
+        List<RealmEntity> realms = getMongoStore().loadEntities(RealmEntity.class, query, invocationContext);
 
         List<RealmModel> results = new ArrayList<RealmModel>();
         for (RealmEntity realmEntity : realms) {
-            results.add(new RealmAdapter(realmEntity, mongoStore, invocationContext));
+            results.add(new RealmAdapter(realmEntity, invocationContext));
         }
         return results;
     }
@@ -86,14 +83,18 @@ public class MongoKeycloakSession implements KeycloakSession {
         DBObject query = new QueryBuilder()
                 .and("name").is(name)
                 .get();
-        RealmEntity realm = mongoStore.loadSingleObject(RealmEntity.class, query, invocationContext);
+        RealmEntity realm = getMongoStore().loadSingleEntity(RealmEntity.class, query, invocationContext);
 
         if (realm == null) return null;
-        return new RealmAdapter(realm, mongoStore, invocationContext);
+        return new RealmAdapter(realm, invocationContext);
     }
 
     @Override
     public boolean removeRealm(String id) {
-        return mongoStore.removeObject(RealmEntity.class, id, invocationContext);
+        return getMongoStore().removeEntity(RealmEntity.class, id, invocationContext);
+    }
+
+    protected MongoStore getMongoStore() {
+        return invocationContext.getMongoStore();
     }
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSessionFactory.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSessionFactory.java
index 6c2af86..7ff4ead 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSessionFactory.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSessionFactory.java
@@ -16,7 +16,6 @@ import org.keycloak.models.mongo.keycloak.entities.RequiredCredentialEntity;
 import org.keycloak.models.mongo.keycloak.entities.RoleEntity;
 import org.keycloak.models.mongo.keycloak.entities.SocialLinkEntity;
 import org.keycloak.models.mongo.keycloak.entities.UserEntity;
-import org.keycloak.models.mongo.utils.EmbeddedMongo;
 import org.keycloak.models.mongo.utils.MongoConfiguration;
 
 import java.net.UnknownHostException;
@@ -40,20 +39,12 @@ public class MongoKeycloakSessionFactory implements KeycloakSessionFactory {
             OAuthClientEntity.class
     };
 
-    private final EmbeddedMongo embeddedMongo;
     private final MongoClient mongoClient;
     private final MongoStore mongoStore;
 
     public MongoKeycloakSessionFactory(MongoConfiguration config) {
         logger.info(String.format("Configuring MongoStore with: " + config));
 
-        if (config.isStartEmbedded()) {
-            embeddedMongo = new EmbeddedMongo();
-            embeddedMongo.startEmbeddedMongo(config.getPort());
-        } else {
-            embeddedMongo = null;
-        }
-
         try {
             // TODO: authentication support
             mongoClient = new MongoClient(config.getHost(), config.getPort());
@@ -75,9 +66,5 @@ public class MongoKeycloakSessionFactory implements KeycloakSessionFactory {
     public void close() {
         logger.info("Closing MongoDB client");
         mongoClient.close();
-
-        if (embeddedMongo != null) {
-            embeddedMongo.stopEmbeddedMongo();
-        }
     }
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/OAuthClientAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/OAuthClientAdapter.java
index 3684872..2eacc45 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/OAuthClientAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/OAuthClientAdapter.java
@@ -3,7 +3,6 @@ package org.keycloak.models.mongo.keycloak.adapters;
 import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
-import org.keycloak.models.mongo.api.MongoStore;
 import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
 import org.keycloak.models.mongo.keycloak.entities.OAuthClientEntity;
 import org.keycloak.models.mongo.keycloak.entities.UserEntity;
@@ -16,14 +15,14 @@ public class OAuthClientAdapter extends AbstractAdapter implements OAuthClientMo
     private final OAuthClientEntity delegate;
     private UserAdapter oauthAgent;
 
-    public OAuthClientAdapter(OAuthClientEntity oauthClientEntity, UserAdapter oauthAgent, MongoStore mongoStore, MongoStoreInvocationContext invContext) {
-        super(mongoStore, invContext);
+    public OAuthClientAdapter(OAuthClientEntity oauthClientEntity, UserAdapter oauthAgent, MongoStoreInvocationContext invContext) {
+        super(invContext);
         this.delegate = oauthClientEntity;
         this.oauthAgent = oauthAgent;
     }
 
-    public OAuthClientAdapter(OAuthClientEntity oauthClientEntity, MongoStore mongoStore, MongoStoreInvocationContext invContext) {
-        this(oauthClientEntity, null, mongoStore, invContext);
+    public OAuthClientAdapter(OAuthClientEntity oauthClientEntity, MongoStoreInvocationContext invContext) {
+        this(oauthClientEntity, null, invContext);
     }
 
     @Override
@@ -35,8 +34,8 @@ public class OAuthClientAdapter extends AbstractAdapter implements OAuthClientMo
     public UserModel getOAuthAgent() {
         // This is not thread-safe. Assumption is that OAuthClientAdapter instance is per-client object
         if (oauthAgent == null) {
-            UserEntity user = mongoStore.loadObject(UserEntity.class, delegate.getOauthAgentId(), invocationContext);
-            oauthAgent = user!=null ? new UserAdapter(user, mongoStore, invocationContext) : null;
+            UserEntity user = getMongoStore().loadEntity(UserEntity.class, delegate.getOauthAgentId(), invocationContext);
+            oauthAgent = user!=null ? new UserAdapter(user, invocationContext) : null;
         }
         return oauthAgent;
     }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
index c5c558c..6083eeb 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
@@ -13,7 +13,6 @@ import org.keycloak.models.SocialLinkModel;
 import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
-import org.keycloak.models.mongo.api.MongoStore;
 import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
 import org.keycloak.models.mongo.keycloak.entities.ApplicationEntity;
 import org.keycloak.models.mongo.keycloak.entities.CredentialEntity;
@@ -54,8 +53,8 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
 
     private volatile transient PasswordPolicy passwordPolicy;
 
-    public RealmAdapter(RealmEntity realmEntity, MongoStore mongoStore, MongoStoreInvocationContext invocationContext) {
-        super(mongoStore, invocationContext);
+    public RealmAdapter(RealmEntity realmEntity, MongoStoreInvocationContext invocationContext) {
+        super(invocationContext);
         this.realm = realmEntity;
     }
 
@@ -280,12 +279,12 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
                 .and("loginName").is(name)
                 .and("realmId").is(getId())
                 .get();
-        UserEntity user = mongoStore.loadSingleObject(UserEntity.class, query, invocationContext);
+        UserEntity user = getMongoStore().loadSingleEntity(UserEntity.class, query, invocationContext);
 
         if (user == null) {
             return null;
         } else {
-            return new UserAdapter(user, mongoStore, invocationContext);
+            return new UserAdapter(user, invocationContext);
         }
     }
 
@@ -295,12 +294,12 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
                 .and("email").is(email)
                 .and("realmId").is(getId())
                 .get();
-        UserEntity user = mongoStore.loadSingleObject(UserEntity.class, query, invocationContext);
+        UserEntity user = getMongoStore().loadSingleEntity(UserEntity.class, query, invocationContext);
 
         if (user == null) {
             return null;
         } else {
-            return new UserAdapter(user, mongoStore, invocationContext);
+            return new UserAdapter(user, invocationContext);
         }
     }
 
@@ -332,8 +331,8 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
         userEntity.setEnabled(true);
         userEntity.setRealmId(getId());
 
-        mongoStore.insertObject(userEntity, invocationContext);
-        return new UserAdapter(userEntity, mongoStore, invocationContext);
+        getMongoStore().insertEntity(userEntity, invocationContext);
+        return new UserAdapter(userEntity, invocationContext);
     }
 
     @Override
@@ -342,7 +341,7 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
                 .and("loginName").is(name)
                 .and("realmId").is(getId())
                 .get();
-        return mongoStore.removeObjects(UserEntity.class, query, invocationContext);
+        return getMongoStore().removeEntities(UserEntity.class, query, invocationContext);
     }
 
     @Override
@@ -351,11 +350,11 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
                 .and("name").is(name)
                 .and("realmId").is(getId())
                 .get();
-        RoleEntity role = mongoStore.loadSingleObject(RoleEntity.class, query, invocationContext);
+        RoleEntity role = getMongoStore().loadSingleEntity(RoleEntity.class, query, invocationContext);
         if (role == null) {
             return null;
         } else {
-            return new RoleAdapter(role, this, mongoStore, invocationContext);
+            return new RoleAdapter(role, this, invocationContext);
         }
     }
 
@@ -372,13 +371,13 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
         roleEntity.setName(name);
         roleEntity.setRealmId(getId());
 
-        mongoStore.insertObject(roleEntity, invocationContext);
-        return new RoleAdapter(roleEntity, this, mongoStore, invocationContext);
+        getMongoStore().insertEntity(roleEntity, invocationContext);
+        return new RoleAdapter(roleEntity, this, invocationContext);
     }
 
     @Override
     public boolean removeRoleById(String id) {
-        return mongoStore.removeObject(RoleEntity.class ,id, invocationContext);
+        return getMongoStore().removeEntity(RoleEntity.class, id, invocationContext);
     }
 
     @Override
@@ -386,13 +385,13 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
         DBObject query = new QueryBuilder()
                 .and("realmId").is(getId())
                 .get();
-        List<RoleEntity> roles = mongoStore.loadObjects(RoleEntity.class, query, invocationContext);
+        List<RoleEntity> roles = getMongoStore().loadEntities(RoleEntity.class, query, invocationContext);
 
         Set<RoleModel> result = new HashSet<RoleModel>();
 
         if (roles == null) return result;
         for (RoleEntity role : roles) {
-            result.add(new RoleAdapter(role, this, mongoStore, invocationContext));
+            result.add(new RoleAdapter(role, this, invocationContext));
         }
 
         return result;
@@ -400,11 +399,11 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
 
     @Override
     public RoleModel getRoleById(String id) {
-        RoleEntity role = mongoStore.loadObject(RoleEntity.class, id, invocationContext);
+        RoleEntity role = getMongoStore().loadEntity(RoleEntity.class, id, invocationContext);
         if (role == null) {
             return null;
         } else {
-            return new RoleAdapter(role, this, mongoStore, invocationContext);
+            return new RoleAdapter(role, this, invocationContext);
         }
     }
 
@@ -420,7 +419,7 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
             addRole(name);
         }
 
-        mongoStore.pushItemToList(realm, "defaultRoles", name, true, invocationContext);
+        getMongoStore().pushItemToList(realm, "defaultRoles", name, true, invocationContext);
     }
 
     @Override
@@ -441,14 +440,14 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
 
     @Override
     public ApplicationModel getApplicationById(String id) {
-        ApplicationEntity appData = mongoStore.loadObject(ApplicationEntity.class, id, invocationContext);
+        ApplicationEntity appData = getMongoStore().loadEntity(ApplicationEntity.class, id, invocationContext);
 
         // Check if application belongs to this realm
         if (appData == null || !getId().equals(appData.getRealmId())) {
             return null;
         }
 
-        return new ApplicationAdapter(appData, mongoStore, invocationContext);
+        return new ApplicationAdapter(appData, invocationContext);
     }
 
     @Override
@@ -457,8 +456,8 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
                 .and("realmId").is(getId())
                 .and("name").is(name)
                 .get();
-        ApplicationEntity appEntity = mongoStore.loadSingleObject(ApplicationEntity.class, query, invocationContext);
-        return appEntity==null ? null : new ApplicationAdapter(appEntity, mongoStore, invocationContext);
+        ApplicationEntity appEntity = getMongoStore().loadSingleEntity(ApplicationEntity.class, query, invocationContext);
+        return appEntity==null ? null : new ApplicationAdapter(appEntity, invocationContext);
     }
 
     @Override
@@ -475,11 +474,11 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
         DBObject query = new QueryBuilder()
                 .and("realmId").is(getId())
                 .get();
-        List<ApplicationEntity> appDatas = mongoStore.loadObjects(ApplicationEntity.class, query, invocationContext);
+        List<ApplicationEntity> appDatas = getMongoStore().loadEntities(ApplicationEntity.class, query, invocationContext);
 
         List<ApplicationModel> result = new ArrayList<ApplicationModel>();
         for (ApplicationEntity appData : appDatas) {
-            result.add(new ApplicationAdapter(appData, mongoStore, invocationContext));
+            result.add(new ApplicationAdapter(appData, invocationContext));
         }
         return result;
     }
@@ -493,14 +492,14 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
         appData.setRealmId(getId());
         appData.setEnabled(true);
         appData.setResourceUserId(resourceUser.getUser().getId());
-        mongoStore.insertObject(appData, invocationContext);
+        getMongoStore().insertEntity(appData, invocationContext);
 
-        return new ApplicationAdapter(appData, resourceUser, mongoStore, invocationContext);
+        return new ApplicationAdapter(appData, resourceUser, invocationContext);
     }
 
     @Override
     public boolean removeApplication(String id) {
-        return mongoStore.removeObject(ApplicationEntity.class, id, invocationContext);
+        return getMongoStore().removeEntity(ApplicationEntity.class, id, invocationContext);
     }
 
     @Override
@@ -517,20 +516,20 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
     @Override
     public void grantRole(UserModel user, RoleModel role) {
         UserEntity userEntity = ((UserAdapter)user).getUser();
-        mongoStore.pushItemToList(userEntity, "roleIds", role.getId(), true, invocationContext);
+        getMongoStore().pushItemToList(userEntity, "roleIds", role.getId(), true, invocationContext);
     }
 
     @Override
     public Set<RoleModel> getRoleMappings(UserModel user) {
         Set<RoleModel> result = new HashSet<RoleModel>();
-        List<RoleEntity> roles = MongoModelUtils.getAllRolesOfUser(user, mongoStore, invocationContext);
+        List<RoleEntity> roles = MongoModelUtils.getAllRolesOfUser(user, invocationContext);
 
         for (RoleEntity role : roles) {
             if (getId().equals(role.getRealmId())) {
-                result.add(new RoleAdapter(role, this, mongoStore, invocationContext));
+                result.add(new RoleAdapter(role, this, invocationContext));
             } else {
                 // Likely applicationRole, but we don't have this application yet
-                result.add(new RoleAdapter(role, mongoStore, invocationContext));
+                result.add(new RoleAdapter(role, invocationContext));
             }
         }
         return result;
@@ -555,20 +554,20 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
     @Override
     public void deleteRoleMapping(UserModel user, RoleModel role) {
         UserEntity userEntity = ((UserAdapter)user).getUser();
-        mongoStore.pullItemFromList(userEntity, "roleIds", role.getId(), invocationContext);
+        getMongoStore().pullItemFromList(userEntity, "roleIds", role.getId(), invocationContext);
     }
 
     @Override
     public Set<RoleModel> getScopeMappings(UserModel user) {
         Set<RoleModel> result = new HashSet<RoleModel>();
-        List<RoleEntity> roles = MongoModelUtils.getAllScopesOfUser(user, mongoStore, invocationContext);
+        List<RoleEntity> roles = MongoModelUtils.getAllScopesOfUser(user, invocationContext);
 
         for (RoleEntity role : roles) {
             if (getId().equals(role.getRealmId())) {
-                result.add(new RoleAdapter(role, this, mongoStore, invocationContext));
+                result.add(new RoleAdapter(role, this, invocationContext));
             } else {
                 // Likely applicationRole, but we don't have this application yet
-                result.add(new RoleAdapter(role, mongoStore, invocationContext));
+                result.add(new RoleAdapter(role, invocationContext));
             }
         }
         return result;
@@ -593,13 +592,13 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
     @Override
     public void addScopeMapping(UserModel agent, RoleModel role) {
         UserEntity userEntity = ((UserAdapter)agent).getUser();
-        mongoStore.pushItemToList(userEntity, "scopeIds", role.getId(), true, invocationContext);
+        getMongoStore().pushItemToList(userEntity, "scopeIds", role.getId(), true, invocationContext);
     }
 
     @Override
     public void deleteScopeMapping(UserModel user, RoleModel role) {
         UserEntity userEntity = ((UserAdapter)user).getUser();
-        mongoStore.pullItemFromList(userEntity, "scopeIds", role.getId(), invocationContext);
+        getMongoStore().pullItemFromList(userEntity, "scopeIds", role.getId(), invocationContext);
     }
 
     @Override
@@ -610,14 +609,14 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
         oauthClient.setOauthAgentId(oauthAgent.getUser().getId());
         oauthClient.setRealmId(getId());
         oauthClient.setName(name);
-        mongoStore.insertObject(oauthClient, invocationContext);
+        getMongoStore().insertEntity(oauthClient, invocationContext);
 
-        return new OAuthClientAdapter(oauthClient, oauthAgent, mongoStore, invocationContext);
+        return new OAuthClientAdapter(oauthClient, oauthAgent, invocationContext);
     }
 
     @Override
     public boolean removeOAuthClient(String id) {
-        return mongoStore.removeObject(OAuthClientEntity.class, id, invocationContext);
+        return getMongoStore().removeEntity(OAuthClientEntity.class, id, invocationContext);
     }
 
     @Override
@@ -628,15 +627,15 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
                 .and("realmId").is(getId())
                 .and("oauthAgentId").is(user.getUser().getId())
                 .get();
-        OAuthClientEntity oauthClient = mongoStore.loadSingleObject(OAuthClientEntity.class, query, invocationContext);
-        return oauthClient == null ? null : new OAuthClientAdapter(oauthClient, user, mongoStore, invocationContext);
+        OAuthClientEntity oauthClient = getMongoStore().loadSingleEntity(OAuthClientEntity.class, query, invocationContext);
+        return oauthClient == null ? null : new OAuthClientAdapter(oauthClient, user, invocationContext);
     }
 
     @Override
     public OAuthClientModel getOAuthClientById(String id) {
-        OAuthClientEntity clientEntity = mongoStore.loadObject(OAuthClientEntity.class, id, invocationContext);
+        OAuthClientEntity clientEntity = getMongoStore().loadEntity(OAuthClientEntity.class, id, invocationContext);
         if (clientEntity == null) return null;
-        return new OAuthClientAdapter(clientEntity, mongoStore, invocationContext);
+        return new OAuthClientAdapter(clientEntity, invocationContext);
     }
 
     @Override
@@ -644,10 +643,10 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
         DBObject query = new QueryBuilder()
                 .and("realmId").is(getId())
                 .get();
-        List<OAuthClientEntity> results = mongoStore.loadObjects(OAuthClientEntity.class, query, invocationContext);
+        List<OAuthClientEntity> results = getMongoStore().loadEntities(OAuthClientEntity.class, query, invocationContext);
         List<OAuthClientModel> list = new ArrayList<OAuthClientModel>();
         for (OAuthClientEntity data : results) {
-            list.add(new OAuthClientAdapter(data, mongoStore, invocationContext));
+            list.add(new OAuthClientAdapter(data, invocationContext));
         }
         return list;
     }
@@ -795,7 +794,7 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
         }
         credentialEntity.setDevice(cred.getDevice());
 
-        mongoStore.updateObject(userEntity, invocationContext);
+        getMongoStore().updateEntity(userEntity, invocationContext);
     }
 
     @Override
@@ -805,8 +804,8 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
                 .and("socialLinks.socialUsername").is(socialLink.getSocialUsername())
                 .and("realmId").is(getId())
                 .get();
-        UserEntity userEntity = mongoStore.loadSingleObject(UserEntity.class, query, invocationContext);
-        return userEntity==null ? null : new UserAdapter(userEntity, mongoStore, invocationContext);
+        UserEntity userEntity = getMongoStore().loadSingleEntity(UserEntity.class, query, invocationContext);
+        return userEntity==null ? null : new UserAdapter(userEntity, invocationContext);
     }
 
     @Override
@@ -833,7 +832,7 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
         socialLinkEntity.setSocialProvider(socialLink.getSocialProvider());
         socialLinkEntity.setSocialUsername(socialLink.getSocialUsername());
 
-        mongoStore.pushItemToList(userEntity, "socialLinks", socialLinkEntity, true, invocationContext);
+        getMongoStore().pushItemToList(userEntity, "socialLinks", socialLinkEntity, true, invocationContext);
     }
 
     @Override
@@ -843,11 +842,11 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
         socialLinkEntity.setSocialUsername(socialLink.getSocialUsername());
 
         UserEntity userEntity = ((UserAdapter)user).getUser();
-        mongoStore.pullItemFromList(userEntity, "socialLinks", socialLinkEntity, invocationContext);
+        getMongoStore().pullItemFromList(userEntity, "socialLinks", socialLinkEntity, invocationContext);
     }
 
     protected void updateRealm() {
-        mongoStore.updateObject(realm, invocationContext);
+        getMongoStore().updateEntity(realm, invocationContext);
     }
 
     protected RequiredCredentialModel initRequiredCredentialModel(String type) {
@@ -863,7 +862,7 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
         DBObject query = new QueryBuilder()
                 .and("realmId").is(getId())
                 .get();
-        List<UserEntity> users = mongoStore.loadObjects(UserEntity.class, query, invocationContext);
+        List<UserEntity> users = getMongoStore().loadEntities(UserEntity.class, query, invocationContext);
         return convertUserEntities(users);
     }
 
@@ -903,7 +902,7 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
                 ).get()
         );
 
-        List<UserEntity> users = mongoStore.loadObjects(UserEntity.class, builder.get(), invocationContext);
+        List<UserEntity> users = getMongoStore().loadEntities(UserEntity.class, builder.get(), invocationContext);
         return convertUserEntities(users);
     }
 
@@ -925,14 +924,14 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
                 queryBuilder.and(UserModel.EMAIL).regex(Pattern.compile("(?i:" + entry.getValue() + "$)"));
             }
         }
-        List<UserEntity> users = mongoStore.loadObjects(UserEntity.class, queryBuilder.get(), invocationContext);
+        List<UserEntity> users = getMongoStore().loadEntities(UserEntity.class, queryBuilder.get(), invocationContext);
         return convertUserEntities(users);
     }
 
     protected List<UserModel> convertUserEntities(List<UserEntity> userEntities) {
         List<UserModel> userModels = new ArrayList<UserModel>();
         for (UserEntity user : userEntities) {
-            userModels.add(new UserAdapter(user, mongoStore, invocationContext));
+            userModels.add(new UserAdapter(user, invocationContext));
         }
         return userModels;
     }
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 b6be681..a3ed40b 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
@@ -10,7 +10,6 @@ import com.mongodb.QueryBuilder;
 import org.keycloak.models.RoleContainerModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
-import org.keycloak.models.mongo.api.MongoStore;
 import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
 import org.keycloak.models.mongo.keycloak.entities.ApplicationEntity;
 import org.keycloak.models.mongo.keycloak.entities.RealmEntity;
@@ -28,15 +27,14 @@ public class RoleAdapter extends AbstractAdapter implements RoleModel {
     private final RoleEntity role;
     private RoleContainerModel roleContainer;
 
-    public RoleAdapter(RoleEntity roleEntity, MongoStore mongoStore, MongoStoreInvocationContext invContext) {
-        this(roleEntity, null, mongoStore, invContext);
+    public RoleAdapter(RoleEntity roleEntity, MongoStoreInvocationContext invContext) {
+        this(roleEntity, null, invContext);
     }
 
-    public RoleAdapter(RoleEntity roleEntity, RoleContainerModel roleContainer, MongoStore mongoStore, MongoStoreInvocationContext invContext) {
-        super(mongoStore, invContext);
+    public RoleAdapter(RoleEntity roleEntity, RoleContainerModel roleContainer, MongoStoreInvocationContext invContext) {
+        super(invContext);
         this.role = roleEntity;
         this.roleContainer = roleContainer;
-        this.mongoStore = mongoStore;
     }
 
     @Override
@@ -72,17 +70,17 @@ public class RoleAdapter extends AbstractAdapter implements RoleModel {
     }
 
     protected void updateRole() {
-        mongoStore.updateObject(role, invocationContext);
+        getMongoStore().updateEntity(role, invocationContext);
     }
 
     @Override
     public void addCompositeRole(RoleModel childRole) {
-        mongoStore.pushItemToList(role, "compositeRoleIds", childRole.getId(), true, invocationContext);
+        getMongoStore().pushItemToList(role, "compositeRoleIds", childRole.getId(), true, invocationContext);
     }
 
     @Override
     public void removeCompositeRole(RoleModel childRole) {
-        mongoStore.pullItemFromList(role, "compositeRoleIds", childRole.getId(), invocationContext);
+        getMongoStore().pullItemFromList(role, "compositeRoleIds", childRole.getId(), invocationContext);
     }
 
     @Override
@@ -94,11 +92,11 @@ public class RoleAdapter extends AbstractAdapter implements RoleModel {
         DBObject query = new QueryBuilder()
                 .and("_id").in(MongoModelUtils.convertStringsToObjectIds(role.getCompositeRoleIds()))
                 .get();
-        List<RoleEntity> childRoles = mongoStore.loadObjects(RoleEntity.class, query, invocationContext);
+        List<RoleEntity> childRoles = getMongoStore().loadEntities(RoleEntity.class, query, invocationContext);
 
         Set<RoleModel> set = new HashSet<RoleModel>();
         for (RoleEntity childRole : childRoles) {
-            set.add(new RoleAdapter(childRole, mongoStore, invocationContext));
+            set.add(new RoleAdapter(childRole, invocationContext));
         }
         return set;
     }
@@ -108,17 +106,17 @@ public class RoleAdapter extends AbstractAdapter implements RoleModel {
         if (roleContainer == null) {
             // Compute it
             if (role.getRealmId() != null) {
-                RealmEntity realm = mongoStore.loadObject(RealmEntity.class, role.getRealmId(), invocationContext);
+                RealmEntity realm = getMongoStore().loadEntity(RealmEntity.class, role.getRealmId(), invocationContext);
                 if (realm == null) {
                     throw new IllegalStateException("Realm with id: " + role.getRealmId() + " doesn't exists");
                 }
-                roleContainer = new RealmAdapter(realm, mongoStore, invocationContext);
+                roleContainer = new RealmAdapter(realm, invocationContext);
             } else if (role.getApplicationId() != null) {
-                ApplicationEntity appEntity = mongoStore.loadObject(ApplicationEntity.class, role.getApplicationId(), invocationContext);
+                ApplicationEntity appEntity = getMongoStore().loadEntity(ApplicationEntity.class, role.getApplicationId(), invocationContext);
                 if (appEntity == null) {
                     throw new IllegalStateException("Application with id: " + role.getApplicationId() + " doesn't exists");
                 }
-                roleContainer = new ApplicationAdapter(appEntity, mongoStore, invocationContext);
+                roleContainer = new ApplicationAdapter(appEntity, invocationContext);
             } else {
                 throw new IllegalStateException("Both realmId and applicationId are null for role: " + this);
             }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
index c66fefa..1a18387 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
@@ -2,7 +2,6 @@ package org.keycloak.models.mongo.keycloak.adapters;
 
 import org.keycloak.models.UserModel;
 import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
-import org.keycloak.models.mongo.api.MongoStore;
 import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
 import org.keycloak.models.mongo.keycloak.entities.UserEntity;
 
@@ -23,8 +22,8 @@ public class UserAdapter extends AbstractAdapter implements UserModel {
 
     private final UserEntity user;
 
-    public UserAdapter(UserEntity userEntity, MongoStore mongoStore, MongoStoreInvocationContext invContext) {
-        super(mongoStore, invContext);
+    public UserAdapter(UserEntity userEntity, MongoStoreInvocationContext invContext) {
+        super(invContext);
         this.user = userEntity;
     }
 
@@ -139,12 +138,12 @@ public class UserAdapter extends AbstractAdapter implements UserModel {
 
     @Override
     public void addWebOrigin(String webOrigin) {
-        mongoStore.pushItemToList(user, "webOrigins", webOrigin, true, invocationContext);
+        getMongoStore().pushItemToList(user, "webOrigins", webOrigin, true, invocationContext);
     }
 
     @Override
     public void removeWebOrigin(String webOrigin) {
-        mongoStore.pullItemFromList(user, "webOrigins", webOrigin, invocationContext);
+        getMongoStore().pullItemFromList(user, "webOrigins", webOrigin, invocationContext);
     }
 
     @Override
@@ -166,12 +165,12 @@ public class UserAdapter extends AbstractAdapter implements UserModel {
 
     @Override
     public void addRedirectUri(String redirectUri) {
-        mongoStore.pushItemToList(user, "redirectUris", redirectUri, true, invocationContext);
+        getMongoStore().pushItemToList(user, "redirectUris", redirectUri, true, invocationContext);
     }
 
     @Override
     public void removeRedirectUri(String redirectUri) {
-        mongoStore.pullItemFromList(user, "redirectUris", redirectUri, invocationContext);
+        getMongoStore().pullItemFromList(user, "redirectUris", redirectUri, invocationContext);
     }
 
     @Override
@@ -185,12 +184,12 @@ public class UserAdapter extends AbstractAdapter implements UserModel {
 
     @Override
     public void addRequiredAction(RequiredAction action) {
-        mongoStore.pushItemToList(user, "requiredActions", action, true, invocationContext);
+        getMongoStore().pushItemToList(user, "requiredActions", action, true, invocationContext);
     }
 
     @Override
     public void removeRequiredAction(RequiredAction action) {
-        mongoStore.pullItemFromList(user, "requiredActions", action, invocationContext);
+        getMongoStore().pullItemFromList(user, "requiredActions", action, invocationContext);
     }
 
     @Override
@@ -205,7 +204,7 @@ public class UserAdapter extends AbstractAdapter implements UserModel {
     }
 
     protected void updateUser() {
-        mongoStore.updateObject(user, invocationContext);
+        getMongoStore().updateEntity(user, invocationContext);
     }
 
     @Override
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/ApplicationEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/ApplicationEntity.java
index 1780581..39a6234 100644
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/ApplicationEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/ApplicationEntity.java
@@ -9,7 +9,6 @@ import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
 import org.keycloak.models.mongo.api.MongoCollection;
 import org.keycloak.models.mongo.api.MongoEntity;
 import org.keycloak.models.mongo.api.MongoField;
-import org.keycloak.models.mongo.api.MongoStore;
 import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
 
 /**
@@ -103,14 +102,14 @@ public class ApplicationEntity extends AbstractMongoIdentifiableEntity implement
     }
 
     @Override
-    public void afterRemove(MongoStore mongoStore, MongoStoreInvocationContext invContext) {
+    public void afterRemove(MongoStoreInvocationContext context) {
         // Remove resourceUser of this application
-        mongoStore.removeObject(UserEntity.class, resourceUserId, invContext);
+        context.getMongoStore().removeEntity(UserEntity.class, resourceUserId, context);
 
         // Remove all roles, which belongs to this application
         DBObject query = new QueryBuilder()
                 .and("applicationId").is(getId())
                 .get();
-        mongoStore.removeObjects(RoleEntity.class, query, invContext);
+        context.getMongoStore().removeEntities(RoleEntity.class, query, context);
     }
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/OAuthClientEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/OAuthClientEntity.java
index 52dfece..f2875b1 100644
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/OAuthClientEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/OAuthClientEntity.java
@@ -4,7 +4,6 @@ import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
 import org.keycloak.models.mongo.api.MongoCollection;
 import org.keycloak.models.mongo.api.MongoEntity;
 import org.keycloak.models.mongo.api.MongoField;
-import org.keycloak.models.mongo.api.MongoStore;
 import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
 
 /**
@@ -46,8 +45,8 @@ public class OAuthClientEntity extends AbstractMongoIdentifiableEntity implement
     }
 
     @Override
-    public void afterRemove(MongoStore mongoStore, MongoStoreInvocationContext invContext) {
+    public void afterRemove(MongoStoreInvocationContext context) {
         // Remove user of this oauthClient
-        mongoStore.removeObject(UserEntity.class, oauthAgentId, invContext);
+        context.getMongoStore().removeEntity(UserEntity.class, oauthAgentId, context);
     }
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/RealmEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/RealmEntity.java
index 34652c7..6ee2fdf 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/RealmEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/RealmEntity.java
@@ -6,7 +6,6 @@ import org.keycloak.models.mongo.api.AbstractMongoIdentifiableEntity;
 import org.keycloak.models.mongo.api.MongoCollection;
 import org.keycloak.models.mongo.api.MongoEntity;
 import org.keycloak.models.mongo.api.MongoField;
-import org.keycloak.models.mongo.api.MongoStore;
 import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
 
 import java.util.ArrayList;
@@ -249,18 +248,18 @@ public class RealmEntity extends AbstractMongoIdentifiableEntity implements Mong
     }
 
     @Override
-    public void afterRemove(MongoStore mongoStore, MongoStoreInvocationContext invContext) {
+    public void afterRemove(MongoStoreInvocationContext context) {
         DBObject query = new QueryBuilder()
                 .and("realmId").is(getId())
                 .get();
 
         // Remove all users of this realm
-        mongoStore.removeObjects(UserEntity.class, query, invContext);
+        context.getMongoStore().removeEntities(UserEntity.class, query, context);
 
         // Remove all roles of this realm
-        mongoStore.removeObjects(RoleEntity.class, query, invContext);
+        context.getMongoStore().removeEntities(RoleEntity.class, query, context);
 
         // Remove all applications of this realm
-        mongoStore.removeObjects(ApplicationEntity.class, query, invContext);
+        context.getMongoStore().removeEntities(ApplicationEntity.class, query, context);
     }
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/RoleEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/RoleEntity.java
index 1aaeac2..e2e9727 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/RoleEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/RoleEntity.java
@@ -74,13 +74,15 @@ public class RoleEntity extends AbstractMongoIdentifiableEntity implements Mongo
     }
 
     @Override
-    public void afterRemove(MongoStore mongoStore, MongoStoreInvocationContext invContext) {
+    public void afterRemove(MongoStoreInvocationContext invContext) {
+        MongoStore mongoStore = invContext.getMongoStore();
+
         // Remove this role from all users, which has it
         DBObject query = new QueryBuilder()
                 .and("roleIds").is(getId())
                 .get();
 
-        List<UserEntity> users = mongoStore.loadObjects(UserEntity.class, query, invContext);
+        List<UserEntity> users = mongoStore.loadEntities(UserEntity.class, query, invContext);
         for (UserEntity user : users) {
             logger.info("Removing role " + getName() + " from user " + user.getLoginName());
             mongoStore.pullItemFromList(user, "roleIds", getId(), invContext);
@@ -91,7 +93,7 @@ public class RoleEntity extends AbstractMongoIdentifiableEntity implements Mongo
                 .and("scopeIds").is(getId())
                 .get();
 
-        users = mongoStore.loadObjects(UserEntity.class, query, invContext);
+        users = mongoStore.loadEntities(UserEntity.class, query, invContext);
         for (UserEntity user : users) {
             logger.info("Removing scope " + getName() + " from user " + user.getLoginName());
             mongoStore.pullItemFromList(user, "scopeIds", getId(), invContext);
@@ -99,7 +101,7 @@ public class RoleEntity extends AbstractMongoIdentifiableEntity implements Mongo
 
         // Remove defaultRoles from realm
         if (realmId != null) {
-            RealmEntity realmEntity = mongoStore.loadObject(RealmEntity.class, realmId, invContext);
+            RealmEntity realmEntity = mongoStore.loadEntity(RealmEntity.class, realmId, invContext);
 
             // Realm might be already removed at this point
             if (realmEntity != null) {
@@ -109,7 +111,7 @@ public class RoleEntity extends AbstractMongoIdentifiableEntity implements Mongo
 
         // Remove defaultRoles from application
         if (applicationId != null) {
-            ApplicationEntity appEntity = mongoStore.loadObject(ApplicationEntity.class, applicationId, invContext);
+            ApplicationEntity appEntity = mongoStore.loadEntity(ApplicationEntity.class, applicationId, invContext);
 
             // Application might be already removed at this point
             if (appEntity != null) {
@@ -121,7 +123,7 @@ public class RoleEntity extends AbstractMongoIdentifiableEntity implements Mongo
         query = new QueryBuilder()
                 .and("compositeRoleIds").is(getId())
                 .get();
-        List<RoleEntity> parentRoles = mongoStore.loadObjects(RoleEntity.class, query, invContext);
+        List<RoleEntity> parentRoles = mongoStore.loadEntities(RoleEntity.class, query, invContext);
         for (RoleEntity role : parentRoles) {
             mongoStore.pullItemFromList(role, "compositeRoleIds", getId(), invContext);
         }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoConfiguration.java b/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoConfiguration.java
index 7a22ae6..7ba22d1 100644
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoConfiguration.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoConfiguration.java
@@ -12,14 +12,12 @@ public class MongoConfiguration {
     private final String dbName;
 
     private final boolean clearCollectionsOnStartup;
-    private final boolean startEmbedded;
 
-    public MongoConfiguration(String host, int port, String dbName, boolean clearCollectionsOnStartup, boolean startEmbedded) {
+    public MongoConfiguration(String host, int port, String dbName, boolean clearCollectionsOnStartup) {
         this.host = host;
         this.port = port;
         this.dbName = dbName;
         this.clearCollectionsOnStartup = clearCollectionsOnStartup;
-        this.startEmbedded = startEmbedded;
     }
 
     public String getHost() {
@@ -38,13 +36,9 @@ public class MongoConfiguration {
         return clearCollectionsOnStartup;
     }
 
-    public boolean isStartEmbedded() {
-        return startEmbedded;
-    }
-
     @Override
     public String toString() {
-        return String.format("MongoConfiguration: host: %s, port: %d, dbName: %s, clearCollectionsOnStartup: %b, startEmbedded: %b",
-                host, port, dbName, clearCollectionsOnStartup, startEmbedded);
+        return String.format("MongoConfiguration: host: %s, port: %d, dbName: %s, clearCollectionsOnStartup: %b",
+                host, port, dbName, clearCollectionsOnStartup);
     }
 }
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 fe4387f..4be29ec 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
@@ -9,7 +9,6 @@ import com.mongodb.DBObject;
 import com.mongodb.QueryBuilder;
 import org.bson.types.ObjectId;
 import org.keycloak.models.UserModel;
-import org.keycloak.models.mongo.api.MongoStore;
 import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
 import org.keycloak.models.mongo.keycloak.adapters.UserAdapter;
 import org.keycloak.models.mongo.keycloak.entities.RoleEntity;
@@ -29,7 +28,7 @@ public class MongoModelUtils {
     }
 
     // Get everything including both application and realm roles
-    public static List<RoleEntity> getAllRolesOfUser(UserModel user, MongoStore mongoStore, MongoStoreInvocationContext invContext) {
+    public static List<RoleEntity> getAllRolesOfUser(UserModel user, MongoStoreInvocationContext invContext) {
         UserEntity userEntity = ((UserAdapter)user).getUser();
         List<String> roleIds = userEntity.getRoleIds();
 
@@ -40,11 +39,11 @@ public class MongoModelUtils {
         DBObject query = new QueryBuilder()
                 .and("_id").in(convertStringsToObjectIds(roleIds))
                 .get();
-        return mongoStore.loadObjects(RoleEntity.class, query, invContext);
+        return invContext.getMongoStore().loadEntities(RoleEntity.class, query, invContext);
     }
 
     // Get everything including both application and realm scopes
-    public static List<RoleEntity> getAllScopesOfUser(UserModel user, MongoStore mongoStore, MongoStoreInvocationContext invContext) {
+    public static List<RoleEntity> getAllScopesOfUser(UserModel user, MongoStoreInvocationContext invContext) {
         UserEntity userEntity = ((UserAdapter)user).getUser();
         List<String> scopeIds = userEntity.getScopeIds();
 
@@ -55,6 +54,6 @@ public class MongoModelUtils {
         DBObject query = new QueryBuilder()
                 .and("_id").in(convertStringsToObjectIds(scopeIds))
                 .get();
-        return mongoStore.loadObjects(RoleEntity.class, query, invContext);
+        return invContext.getMongoStore().loadEntities(RoleEntity.class, query, invContext);
     }
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/utils/SystemPropertiesConfigurationProvider.java b/model/mongo/src/main/java/org/keycloak/models/mongo/utils/SystemPropertiesConfigurationProvider.java
index d30786f..ce24c63 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/utils/SystemPropertiesConfigurationProvider.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/utils/SystemPropertiesConfigurationProvider.java
@@ -8,39 +8,39 @@ public class SystemPropertiesConfigurationProvider {
     private static final String MONGO_HOST = "keycloak.mongo.host";
     private static final String MONGO_PORT = "keycloak.mongo.port";
     private static final String MONGO_DB_NAME = "keycloak.mongo.db";
-    private static final String MONGO_CLEAR_COLLECTIONS_ON_STARTUP = "keycloak.mongo.clearCollectionsOnStartup";
-    private static final String MONGO_START_EMBEDDED = "keycloak.mongo.startEmbedded";
+    private static final String MONGO_CLEAR_ON_STARTUP = "keycloak.mongo.clearOnStartup";
 
-    // Port where MongoDB instance is normally started on linux. This port should be used if we're not starting embedded instance
-    private static final int MONGO_DEFAULT_PORT = 27017;
+    // Property names from Liveoak . Those are used as fallback in case that original value is not available
+    private static final String MONGO_HOST_2 = "mongo.host";
+    private static final String MONGO_PORT_2 = "mongo.port";
+    private static final String MONGO_DB_NAME_2 = "mongo.db";
+    private static final String MONGO_CLEAR_ON_STARTUP_2 = "mongo.clearCollectionsOnStartup";
 
-    // Port where embedded MongoDB instance will be started. Same port will be used by KeycloakApplication then
-    public static final int MONGO_DEFAULT_PORT_EMBEDDED = 27018;
+    // Port where MongoDB instance is normally started on linux. This port should be used if we're not starting embedded instance
+    private static final String MONGO_DEFAULT_PORT = "27017";
 
     public static String getMongoHost() {
-        return System.getProperty(MONGO_HOST, "localhost");
+        return getSystemPropertyWithFallback(MONGO_HOST, MONGO_HOST_2, "localhost");
     }
 
     public static int getMongoPort() {
-        String portProp = System.getProperty(MONGO_PORT);
-        if (portProp != null) {
-            return Integer.parseInt(portProp);
-        } else {
-            // Default port is 27017 in case of non-embedded, and 27018 in case of embedded
-            return isStartEmbedded() ? MONGO_DEFAULT_PORT_EMBEDDED : MONGO_DEFAULT_PORT;
-        }
+        String portProp = getSystemPropertyWithFallback(MONGO_PORT, MONGO_PORT_2, MONGO_DEFAULT_PORT);
+        return Integer.parseInt(portProp);
     }
 
     public static String getMongoDbName() {
-        return System.getProperty(MONGO_DB_NAME, "keycloak");
+        return getSystemPropertyWithFallback(MONGO_DB_NAME, MONGO_DB_NAME_2, "keycloak");
     }
 
     public static boolean isClearCollectionsOnStartup() {
-        return Boolean.parseBoolean(System.getProperty(MONGO_CLEAR_COLLECTIONS_ON_STARTUP, "true"));
+        String property = getSystemPropertyWithFallback(MONGO_CLEAR_ON_STARTUP, MONGO_CLEAR_ON_STARTUP_2, "false");
+        return "true".equalsIgnoreCase(property);
     }
 
-    public static boolean isStartEmbedded() {
-        return Boolean.parseBoolean(System.getProperty(MONGO_START_EMBEDDED, "false"));
+    // Check if property propName1 (like "keycloak.mongo.host" is available and if not, then fallback to property "mongo.host" )
+    private static String getSystemPropertyWithFallback(String propName1, String propName2, String defaultValue) {
+        String propValue1 = System.getProperty(propName1);
+        return propValue1!=null ? propValue1 : System.getProperty(propName2, defaultValue);
     }
 
     // Create configuration based on system properties
@@ -49,8 +49,7 @@ public class SystemPropertiesConfigurationProvider {
                 getMongoHost(),
                 getMongoPort(),
                 getMongoDbName(),
-                isClearCollectionsOnStartup(),
-                isStartEmbedded()
+                isClearCollectionsOnStartup()
         );
     }
 }
diff --git a/model/mongo/src/test/java/org/keycloak/models/mongo/test/MongoDBModelTest.java b/model/mongo/src/test/java/org/keycloak/models/mongo/test/MongoDBModelTest.java
index b2d093d..7ee8141 100755
--- a/model/mongo/src/test/java/org/keycloak/models/mongo/test/MongoDBModelTest.java
+++ b/model/mongo/src/test/java/org/keycloak/models/mongo/test/MongoDBModelTest.java
@@ -12,8 +12,8 @@ import org.keycloak.models.mongo.api.MongoEntity;
 import org.keycloak.models.mongo.api.MongoStore;
 import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
 import org.keycloak.models.mongo.impl.MongoStoreImpl;
-import org.keycloak.models.mongo.impl.context.SimpleMongoStoreInvocationContext;
 import org.keycloak.models.mongo.impl.context.TransactionMongoStoreInvocationContext;
+import org.keycloak.models.mongo.utils.SystemPropertiesConfigurationProvider;
 
 import java.net.UnknownHostException;
 import java.util.ArrayList;
@@ -37,7 +37,7 @@ public class MongoDBModelTest {
     public void before() throws Exception {
         try {
             // TODO: authentication support
-            mongoClient = new MongoClient("localhost", 27017);
+            mongoClient = new MongoClient("localhost", SystemPropertiesConfigurationProvider.getMongoPort());
 
             DB db = mongoClient.getDB("keycloakTest");
             mongoStore = new MongoStoreImpl(db, true, MANAGED_DATA_TYPES);
@@ -62,7 +62,7 @@ public class MongoDBModelTest {
         john.setAge(25);
         john.setGender(Person.Gender.MALE);
 
-        mongoStore.insertObject(john, context);
+        mongoStore.insertEntity(john, context);
 
         // Add another user
         Person mary = new Person();
@@ -83,12 +83,12 @@ public class MongoDBModelTest {
         mary.setGender(Person.Gender.FEMALE);
         mary.setGenders(asList(Person.Gender.FEMALE));
 
-        mongoStore.insertObject(mary, context);
+        mongoStore.insertEntity(mary, context);
 
-        Assert.assertEquals(2, mongoStore.loadObjects(Person.class, new QueryBuilder().get(), context).size());
+        Assert.assertEquals(2, mongoStore.loadEntities(Person.class, new QueryBuilder().get(), context).size());
 
         DBObject query = new QueryBuilder().and("addresses.flatNumbers").is("flat1").get();
-        List<Person> persons = mongoStore.loadObjects(Person.class, query, context);
+        List<Person> persons = mongoStore.loadEntities(Person.class, query, context);
         Assert.assertEquals(1, persons.size());
         mary = persons.get(0);
         Assert.assertEquals(mary.getFirstName(), "mary");
@@ -105,7 +105,7 @@ public class MongoDBModelTest {
         addr3.setStreet("Broadway");
         mongoStore.pushItemToList(mary, "addresses", addr3, true, context);
 
-        mary = mongoStore.loadObject(Person.class, mary.getId(), context);
+        mary = mongoStore.loadEntity(Person.class, mary.getId(), context);
         Assert.assertEquals(3, mary.getKids().size());
         Assert.assertTrue(mary.getKids().contains("Pauline"));
         Assert.assertFalse(mary.getKids().contains("Paul"));
@@ -121,16 +121,16 @@ public class MongoDBModelTest {
         mary.addAttribute("attr1", "value1");
         mary.addAttribute("attr2", "value2");
         mary.addAttribute("attr.some3", "value3");
-        mongoStore.updateObject(mary, context);
+        mongoStore.updateEntity(mary, context);
 
-        mary = mongoStore.loadObject(Person.class, mary.getId(), context);
+        mary = mongoStore.loadEntity(Person.class, mary.getId(), context);
         Assert.assertEquals(3, mary.getAttributes().size());
 
         mary.removeAttribute("attr2");
         mary.removeAttribute("nonExisting");
-        mongoStore.updateObject(mary, context);
+        mongoStore.updateEntity(mary, context);
 
-        mary = mongoStore.loadObject(Person.class, mary.getId(), context);
+        mary = mongoStore.loadEntity(Person.class, mary.getId(), context);
         Assert.assertEquals(2, mary.getAttributes().size());
         Assert.assertEquals("value1", mary.getAttributes().get("attr1"));
         Assert.assertEquals("value3", mary.getAttributes().get("attr.some3"));

model/pom.xml 1(+1 -0)

diff --git a/model/pom.xml b/model/pom.xml
index 3301b71..41d5be1 100755
--- a/model/pom.xml
+++ b/model/pom.xml
@@ -38,5 +38,6 @@
         <!-- <module>picketlink</module> -->
         <module>jpa</module>
         <module>mongo</module>
+        <module>tests</module>
     </modules>
 </project>

model/tests/pom.xml 69(+69 -0)

diff --git a/model/tests/pom.xml b/model/tests/pom.xml
new file mode 100644
index 0000000..c4d7330
--- /dev/null
+++ b/model/tests/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.0-alpha-2-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-model-tests</artifactId>
+    <name>Keycloak Model Tests</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-services</artifactId>
+            <version>${project.version}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+            <scope>compile</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>package-tests-jar</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <skipTests>true</skipTests>
+                </configuration>
+            </plugin>
+
+        </plugins>
+    </build>
+
+</project>

pom.xml 12(+6 -6)

diff --git a/pom.xml b/pom.xml
index fc58b75..91b0818 100755
--- a/pom.xml
+++ b/pom.xml
@@ -314,11 +314,6 @@
                 <version>2.11.2</version>
             </dependency>
             <dependency>
-                <groupId>de.flapdoodle.embed</groupId>
-                <artifactId>de.flapdoodle.embed.mongo</artifactId>
-                <version>1.40</version>
-            </dependency>
-            <dependency>
                 <groupId>org.apache.jmeter</groupId>
                 <artifactId>ApacheJMeter_java</artifactId>
                 <version>2.9</version>
@@ -395,7 +390,7 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-surefire-plugin</artifactId>
-                    <!-- <version>2.5</version> -->
+                    <version>2.16</version>
                     <configuration>
                         <forkMode>once</forkMode>
                         <argLine>-Xms512m -Xmx512m</argLine>
@@ -479,6 +474,11 @@
                     <artifactId>exec-maven-plugin</artifactId>
                     <version>1.2.1</version>
                 </plugin>
+                <plugin>
+                    <groupId>com.github.joelittlejohn.embedmongo</groupId>
+                    <artifactId>embedmongo-maven-plugin</artifactId>
+                    <version>0.1.10</version>
+                </plugin>
             </plugins>
         </pluginManagement>
 

services/pom.xml 65(+0 -65)

diff --git a/services/pom.xml b/services/pom.xml
index de0ae59..969dc68 100755
--- a/services/pom.xml
+++ b/services/pom.xml
@@ -56,41 +56,6 @@
             <artifactId>keycloak-jaxrs-oauth-client</artifactId>
             <version>${project.version}</version>
         </dependency>
-
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-jpa</artifactId>
-            <version>${project.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <!--
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-picketlink</artifactId>
-            <version>${project.version}</version>
-            <scope>test</scope>
-        </dependency>
-        -->
-
-        <!-- TODO: remove -->
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-model-mongo</artifactId>
-            <version>${project.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.mongodb</groupId>
-            <artifactId>mongo-java-driver</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.picketlink</groupId>
-            <artifactId>picketlink-common</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-
         <dependency>
             <groupId>org.keycloak</groupId>
             <artifactId>keycloak-social-core</artifactId>
@@ -142,21 +107,6 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-undertow</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-servlet</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-core</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
             <groupId>org.codehaus.jackson</groupId>
             <artifactId>jackson-core-asl</artifactId>
             <scope>provided</scope>
@@ -186,21 +136,6 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.hibernate.javax.persistence</groupId>
-            <artifactId>hibernate-jpa-2.0-api</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.h2database</groupId>
-            <artifactId>h2</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate</groupId>
-            <artifactId>hibernate-entitymanager</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
             <groupId>com.icegreen</groupId>
             <artifactId>greenmail</artifactId>
             <scope>test</scope>
diff --git a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
index 080e28f..83bdaca 100755
--- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
+++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
@@ -8,7 +8,7 @@ import org.keycloak.services.managers.ApplianceBootstrap;
 import org.keycloak.services.managers.SocialRequestManager;
 import org.keycloak.services.managers.TokenManager;
 import org.keycloak.services.resources.admin.AdminService;
-import org.keycloak.services.utils.ModelProviderUtils;
+import org.keycloak.models.utils.ModelProviderUtils;
 
 import javax.servlet.ServletContext;
 import javax.ws.rs.core.Application;
diff --git a/testsuite/integration/pom.xml b/testsuite/integration/pom.xml
index 9489da1..d668ee8 100755
--- a/testsuite/integration/pom.xml
+++ b/testsuite/integration/pom.xml
@@ -350,11 +350,72 @@
 
             <properties>
                 <keycloak.mongo.host>localhost</keycloak.mongo.host>
-                <keycloak.mongo.port>27017</keycloak.mongo.port>
+                <keycloak.mongo.port>27018</keycloak.mongo.port>
                 <keycloak.mongo.db>keycloak</keycloak.mongo.db>
-                <keycloak.mongo.clearCollectionsOnStartup>true</keycloak.mongo.clearCollectionsOnStartup>
+                <keycloak.mongo.clearOnStartup>true</keycloak.mongo.clearOnStartup>
             </properties>
 
+            <build>
+                <plugins>
+
+                    <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>test</id>
+                                <phase>integration-test</phase>
+                                <goals>
+                                    <goal>test</goal>
+                                </goals>
+                                <configuration>
+                                    <systemPropertyVariables>
+                                        <keycloak.mongo.host>${keycloak.mongo.host}</keycloak.mongo.host>
+                                        <keycloak.mongo.port>${keycloak.mongo.port}</keycloak.mongo.port>
+                                        <keycloak.mongo.db>${keycloak.mongo.db}</keycloak.mongo.db>
+                                        <keycloak.mongo.clearOnStartup>${keycloak.mongo.clearOnStartup}</keycloak.mongo.clearOnStartup>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>default-test</id>
+                                <configuration>
+                                    <skip>true</skip>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+
+                    <!-- Embedded mongo -->
+                    <plugin>
+                        <groupId>com.github.joelittlejohn.embedmongo</groupId>
+                        <artifactId>embedmongo-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>start-mongodb</id>
+                                <phase>pre-integration-test</phase>
+                                <goals>
+                                    <goal>start</goal>
+                                </goals>
+                                <configuration>
+                                    <port>${keycloak.mongo.port}</port>
+                                    <logging>file</logging>
+                                    <logFile>${project.build.directory}/mongodb.log</logFile>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>stop-mongodb</id>
+                                <phase>post-integration-test</phase>
+                                <goals>
+                                    <goal>stop</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+
         </profile>
     </profiles>
 </project>
\ No newline at end of file
diff --git a/testsuite/integration/README.md b/testsuite/integration/README.md
index 6428657..1b3ed3e 100644
--- a/testsuite/integration/README.md
+++ b/testsuite/integration/README.md
@@ -8,6 +8,13 @@ The testsuite uses Sellenium. By default it uses the HtmlUnit WebDriver, but can
 
 To run the tests with Firefox add `-Dbrowser=firefox` or for Chrome add `-Dbrowser=chrome`
 
+Mongo
+-----
+
+The testsuite is executed with JPA model implementation with data saved in H2 database by default. To run testsuite with Mongo model, just add property `-Dkeycloak.model=mongo` when executing it.
+
+Note that this will automatically run embedded Mongo database on localhost/27018 and it will stop it after whole testsuite is finished.
+So you don't need to have Mongo installed on your laptop to run mongo execution tests.
 
 Test utils
 ==========
@@ -41,6 +48,16 @@ For example to use the example themes run the server with:
     
 **NOTE:** If `keycloak.theme.dir` is specified the default themes (base, rcue and keycloak) are loaded from the classpath
 
+### Run server with Mongo model
+
+To start a Keycloak server with identity model data persisted in Mongo database instead of default JPA/H2 you can run:
+
+    mvn exec:java -Pkeycloak-server -Dkeycloak.model=mongo
+
+By default it's using database `keycloak` on localhost/27017 and it uses already existing data from this DB (no cleanup of existing data during bootstrap). Assumption is that you already have DB running on localhost/27017 . Use system properties to configure things differently:
+
+    mvn exec:java -Pkeycloak-server -Dkeycloak.model=mongo -Dkeycloak.mongo.host=localhost -Dkeycloak.mongo.port=27017 -Dkeycloak.mongo.db=keycloak -Dkeycloak.mongo.clearCollectionsOnStartup=false
+
 TOTP codes
 ----------