keycloak-memoizeit

Adding TypeConverters. AdapterTest.test1CreateRealm()

8/30/2013 2:23:50 PM

Changes

services/src/main/java/org/keycloak/services/models/nosql/adapters/NoSQLRealm.java 49(+0 -49)

services/src/main/java/org/keycloak/services/models/nosql/impl/Test.java 53(+0 -53)

Details

diff --git a/services/src/main/java/org/keycloak/services/models/nosql/adapters/MongoDBSessionFactory.java b/services/src/main/java/org/keycloak/services/models/nosql/adapters/MongoDBSessionFactory.java
new file mode 100644
index 0000000..1c82f49
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/models/nosql/adapters/MongoDBSessionFactory.java
@@ -0,0 +1,43 @@
+package org.keycloak.services.models.nosql.adapters;
+
+import java.net.UnknownHostException;
+
+import com.mongodb.DB;
+import com.mongodb.MongoClient;
+import org.keycloak.services.models.KeycloakSession;
+import org.keycloak.services.models.KeycloakSessionFactory;
+import org.keycloak.services.models.nosql.api.NoSQL;
+import org.keycloak.services.models.nosql.impl.MongoDBImpl;
+
+/**
+ * NoSQL implementation based on MongoDB
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class MongoDBSessionFactory implements KeycloakSessionFactory {
+
+    private final MongoClient mongoClient;
+    private final NoSQL mongoDB;
+
+    public MongoDBSessionFactory(String host, int port, String dbName) {
+        try {
+            // TODO: authentication support
+            mongoClient = new MongoClient(host, port);
+
+            DB db = mongoClient.getDB(dbName);
+            mongoDB = new MongoDBImpl(db);
+        } catch (UnknownHostException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public KeycloakSession createSession() {
+        return new NoSQLSession(mongoDB);
+    }
+
+    @Override
+    public void close() {
+        mongoClient.close();
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/models/nosql/adapters/NoSQLSession.java b/services/src/main/java/org/keycloak/services/models/nosql/adapters/NoSQLSession.java
new file mode 100644
index 0000000..10e5413
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/models/nosql/adapters/NoSQLSession.java
@@ -0,0 +1,67 @@
+package org.keycloak.services.models.nosql.adapters;
+
+import java.util.List;
+
+import org.jboss.resteasy.spi.NotImplementedYetException;
+import org.keycloak.services.models.KeycloakSession;
+import org.keycloak.services.models.KeycloakTransaction;
+import org.keycloak.services.models.RealmModel;
+import org.keycloak.services.models.UserModel;
+import org.keycloak.services.models.nosql.data.RealmData;
+import org.keycloak.services.models.nosql.api.NoSQL;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class NoSQLSession implements KeycloakSession {
+
+    private static final NoSQLTransaction PLACEHOLDER = new NoSQLTransaction();
+    private final NoSQL noSQL;
+
+    public NoSQLSession(NoSQL noSQL) {
+        this.noSQL = noSQL;
+    }
+
+    @Override
+    public KeycloakTransaction getTransaction() {
+        return PLACEHOLDER;
+    }
+
+    @Override
+    public void close() {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public RealmModel createRealm(String name) {
+        RealmData newRealm = new RealmData();
+        newRealm.setName(name);
+
+        noSQL.saveObject(newRealm);
+
+        RealmAdapter realm = new RealmAdapter(newRealm, noSQL);
+        return realm;
+    }
+
+    @Override
+    public RealmModel createRealm(String id, String name) {
+        // Ignore ID for now. It seems that it exists just for workaround picketlink
+        return createRealm(name);
+    }
+
+    @Override
+    public RealmModel getRealm(String id) {
+        RealmData realmData = noSQL.loadObject(RealmData.class, id);
+        return new RealmAdapter(realmData, noSQL);
+    }
+
+    @Override
+    public List<RealmModel> getRealms(UserModel admin) {
+        throw new NotImplementedYetException();
+    }
+
+    @Override
+    public void deleteRealm(RealmModel realm) {
+        noSQL.removeObject(RealmData.class, realm.getId());
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/models/nosql/adapters/NoSQLTransaction.java b/services/src/main/java/org/keycloak/services/models/nosql/adapters/NoSQLTransaction.java
new file mode 100644
index 0000000..60a1338
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/models/nosql/adapters/NoSQLTransaction.java
@@ -0,0 +1,39 @@
+package org.keycloak.services.models.nosql.adapters;
+
+import org.keycloak.services.models.KeycloakTransaction;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class NoSQLTransaction implements KeycloakTransaction {
+
+    @Override
+    public void begin() {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void commit() {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void rollback() {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void setRollbackOnly() {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean getRollbackOnly() {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean isActive() {
+        return true;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/models/nosql/adapters/RealmAdapter.java b/services/src/main/java/org/keycloak/services/models/nosql/adapters/RealmAdapter.java
new file mode 100644
index 0000000..58f73ef
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/models/nosql/adapters/RealmAdapter.java
@@ -0,0 +1,492 @@
+package org.keycloak.services.models.nosql.adapters;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.bouncycastle.openssl.PEMWriter;
+import org.jboss.resteasy.security.PemUtils;
+import org.keycloak.services.models.ApplicationModel;
+import org.keycloak.services.models.RealmModel;
+import org.keycloak.services.models.RequiredCredentialModel;
+import org.keycloak.services.models.RoleModel;
+import org.keycloak.services.models.SocialLinkModel;
+import org.keycloak.services.models.UserCredentialModel;
+import org.keycloak.services.models.UserModel;
+import org.keycloak.services.models.nosql.api.NoSQL;
+import org.keycloak.services.models.nosql.api.NoSQLQuery;
+import org.keycloak.services.models.nosql.data.RealmData;
+import org.keycloak.services.models.nosql.data.RoleData;
+import org.keycloak.services.models.nosql.data.UserData;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class RealmAdapter implements RealmModel {
+
+    private final RealmData realm;
+    private final NoSQL noSQL;
+
+    protected volatile transient PublicKey publicKey;
+    protected volatile transient PrivateKey privateKey;
+
+    public RealmAdapter(RealmData realmData, NoSQL noSQL) {
+        this.realm = realmData;
+        this.noSQL = noSQL;
+    }
+
+    @Override
+    public String getId() {
+        return realm.getId();
+    }
+
+    @Override
+    public String getName() {
+        return realm.getName();
+    }
+
+    @Override
+    public void setName(String name) {
+        realm.setName(name);
+        updateRealm();
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return realm.isEnabled();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        realm.setEnabled(enabled);
+        updateRealm();
+    }
+
+    @Override
+    public boolean isSocial() {
+        return realm.isSocial();
+    }
+
+    @Override
+    public void setSocial(boolean social) {
+        realm.setSocial(social);
+        updateRealm();
+    }
+
+    @Override
+    public boolean isAutomaticRegistrationAfterSocialLogin() {
+        return realm.isAutomaticRegistrationAfterSocialLogin();
+    }
+
+    @Override
+    public void setAutomaticRegistrationAfterSocialLogin(boolean automaticRegistrationAfterSocialLogin) {
+        realm.setAutomaticRegistrationAfterSocialLogin(automaticRegistrationAfterSocialLogin);
+        updateRealm();
+    }
+
+    @Override
+    public boolean isSslNotRequired() {
+        return realm.isSslNotRequired();
+    }
+
+    @Override
+    public void setSslNotRequired(boolean sslNotRequired) {
+        realm.setSslNotRequired(sslNotRequired);
+        updateRealm();
+    }
+
+    @Override
+    public boolean isCookieLoginAllowed() {
+        return realm.isCookieLoginAllowed();
+    }
+
+    @Override
+    public void setCookieLoginAllowed(boolean cookieLoginAllowed) {
+        realm.setCookieLoginAllowed(cookieLoginAllowed);
+        updateRealm();
+    }
+
+    @Override
+    public boolean isRegistrationAllowed() {
+        return realm.isRegistrationAllowed();
+    }
+
+    @Override
+    public void setRegistrationAllowed(boolean registrationAllowed) {
+        realm.setRegistrationAllowed(registrationAllowed);
+        updateRealm();
+    }
+
+    @Override
+    public int getTokenLifespan() {
+        return realm.getTokenLifespan();
+    }
+
+    @Override
+    public void setTokenLifespan(int tokenLifespan) {
+        realm.setTokenLifespan(tokenLifespan);
+        updateRealm();
+    }
+
+    @Override
+    public int getAccessCodeLifespan() {
+        return realm.getAccessCodeLifespan();
+    }
+
+    @Override
+    public void setAccessCodeLifespan(int accessCodeLifespan) {
+        realm.setAccessCodeLifespan(accessCodeLifespan);
+        updateRealm();
+    }
+
+    @Override
+    public String getPublicKeyPem() {
+        return realm.getPublicKeyPem();
+    }
+
+    @Override
+    public void setPublicKeyPem(String publicKeyPem) {
+        realm.setPublicKeyPem(publicKeyPem);
+        this.publicKey = null;
+        updateRealm();
+    }
+
+    @Override
+    public String getPrivateKeyPem() {
+        return realm.getPrivateKeyPem();
+    }
+
+    @Override
+    public void setPrivateKeyPem(String privateKeyPem) {
+        realm.setPrivateKeyPem(privateKeyPem);
+        this.privateKey = null;
+        updateRealm();
+    }
+
+    @Override
+    public PublicKey getPublicKey() {
+        if (publicKey != null) return publicKey;
+        String pem = getPublicKeyPem();
+        if (pem != null) {
+            try {
+                publicKey = PemUtils.decodePublicKey(pem);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+        return publicKey;
+    }
+
+    @Override
+    public void setPublicKey(PublicKey publicKey) {
+        this.publicKey = publicKey;
+        StringWriter writer = new StringWriter();
+        PEMWriter pemWriter = new PEMWriter(writer);
+        try {
+            pemWriter.writeObject(publicKey);
+            pemWriter.flush();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        String s = writer.toString();
+        setPublicKeyPem(PemUtils.removeBeginEnd(s));
+    }
+
+    @Override
+    public PrivateKey getPrivateKey() {
+        if (privateKey != null) return privateKey;
+        String pem = getPrivateKeyPem();
+        if (pem != null) {
+            try {
+                privateKey = PemUtils.decodePrivateKey(pem);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+        return privateKey;
+    }
+
+    @Override
+    public void setPrivateKey(PrivateKey privateKey) {
+        this.privateKey = privateKey;
+        StringWriter writer = new StringWriter();
+        PEMWriter pemWriter = new PEMWriter(writer);
+        try {
+            pemWriter.writeObject(privateKey);
+            pemWriter.flush();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        String s = writer.toString();
+        setPrivateKeyPem(PemUtils.removeBeginEnd(s));
+    }
+
+    @Override
+    public List<RequiredCredentialModel> getRequiredCredentials() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void addRequiredCredential(String cred) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean validatePassword(UserModel user, String password) {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean validateTOTP(UserModel user, String password, String token) {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void updateCredential(UserModel user, UserCredentialModel cred) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public UserModel getUser(String name) {
+        NoSQLQuery query = NoSQLQuery.create().put("loginName", name).put("realmId", getId());
+        UserData user = noSQL.loadSingleObject(UserData.class, query);
+
+        if (user == null) {
+            return null;
+        } else {
+            return new UserAdapter(user, noSQL);
+        }
+    }
+
+    @Override
+    public UserModel addUser(String username) {
+        if (getUser(username) != null) {
+            throw new IllegalArgumentException("User " + username + " already exists");
+        }
+
+        UserData userData = new UserData();
+        userData.setLoginName(username);
+        userData.setEnabled(true);
+        userData.setRealmId(getId());
+
+        noSQL.saveObject(userData);
+        return new UserAdapter(userData, noSQL);
+    }
+
+    @Override
+    public RoleAdapter getRole(String name) {
+        NoSQLQuery query = NoSQLQuery.create().put("name", name).put("realmId", getId());
+        RoleData role = noSQL.loadSingleObject(RoleData.class, query);
+        if (role == null) {
+            return null;
+        } else {
+            return new RoleAdapter(role, noSQL);
+        }
+    }
+
+    @Override
+    public RoleModel addRole(String name) {
+        if (getRole(name) != null) {
+            throw new IllegalArgumentException("Role " + name + " already exists");
+        }
+
+        RoleData roleData = new RoleData();
+        roleData.setName(name);
+        roleData.setRealmId(getId());
+
+        noSQL.saveObject(roleData);
+        return new RoleAdapter(roleData, noSQL);
+    }
+
+    @Override
+    public List<RoleModel> getRoles() {
+        NoSQLQuery query = NoSQLQuery.create().put("realmId", getId());
+        List<RoleData> roles = noSQL.loadObjects(RoleData.class, query);
+
+        List<RoleModel> result = new ArrayList<RoleModel>();
+        for (RoleData role : roles) {
+            result.add(new RoleAdapter(role, noSQL));
+        }
+
+        return result;
+    }
+
+    @Override
+    public List<RoleModel> getDefaultRoles() {
+        List<RoleModel> defaultRoleModels = new ArrayList<RoleModel>();
+        if (realm.getDefaultRoles() != null) {
+            for (String name : realm.getDefaultRoles()) {
+                RoleAdapter role = getRole(name);
+                if (role != null) {
+                    defaultRoleModels.add(role);
+                }
+            }
+        }
+        return defaultRoleModels;
+    }
+
+    @Override
+    public void addDefaultRole(String name) {
+        if (getRole(name) == null) {
+            addRole(name);
+        }
+
+        String[] defaultRoles = realm.getDefaultRoles();
+        if (defaultRoles == null) {
+            defaultRoles = new String[1];
+        } else {
+            defaultRoles = Arrays.copyOf(defaultRoles, defaultRoles.length + 1);
+        }
+        defaultRoles[defaultRoles.length - 1] = name;
+
+        realm.setDefaultRoles(defaultRoles);
+        updateRealm();
+    }
+
+    @Override
+    public void updateDefaultRoles(String[] defaultRoles) {
+        for (String name : defaultRoles) {
+            if (getRole(name) == null) {
+                addRole(name);
+            }
+        }
+
+        realm.setDefaultRoles(defaultRoles);
+        updateRealm();
+    }
+
+    @Override
+    public Map<String, ApplicationModel> getResourceNameMap() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public List<ApplicationModel> getApplications() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public ApplicationModel addApplication(String name) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean hasRole(UserModel user, RoleModel role) {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void grantRole(UserModel user, RoleModel role) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public Set<String> getRoleMappings(UserModel user) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void addScope(UserModel agent, String roleName) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public Set<String> getScope(UserModel agent) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean isRealmAdmin(UserModel agent) {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void addRealmAdmin(UserModel agent) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public RoleModel getRoleById(String id) {
+        RoleData role = noSQL.loadObject(RoleData.class, id);
+        if (role == null) {
+            return null;
+        } else {
+            return new RoleAdapter(role, noSQL);
+        }
+    }
+
+    @Override
+    public List<RequiredCredentialModel> getRequiredApplicationCredentials() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public List<RequiredCredentialModel> getRequiredOAuthClientCredentials() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean hasRole(UserModel user, String role) {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public ApplicationModel getApplicationById(String id) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void addRequiredOAuthClientCredential(String type) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void addRequiredResourceCredential(String type) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void updateRequiredCredentials(Set<String> creds) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void updateRequiredOAuthClientCredentials(Set<String> creds) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void updateRequiredApplicationCredentials(Set<String> creds) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public UserModel getUserBySocialLink(SocialLinkModel socialLink) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public Set<SocialLinkModel> getSocialLinks(UserModel user) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void addSocialLink(UserModel user, SocialLinkModel socialLink) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void removeSocialLink(UserModel user, SocialLinkModel socialLink) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    protected void updateRealm() {
+        noSQL.saveObject(realm);
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/models/nosql/adapters/RoleAdapter.java b/services/src/main/java/org/keycloak/services/models/nosql/adapters/RoleAdapter.java
new file mode 100644
index 0000000..edde2e4
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/models/nosql/adapters/RoleAdapter.java
@@ -0,0 +1,49 @@
+package org.keycloak.services.models.nosql.adapters;
+
+import org.keycloak.services.models.RoleModel;
+import org.keycloak.services.models.nosql.api.NoSQL;
+import org.keycloak.services.models.nosql.data.RoleData;
+import org.keycloak.services.models.nosql.data.UserData;
+
+/**
+ * Wrapper around RoleData object, which will persist wrapped object after each set operation (compatibility with picketlink based impl)
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class RoleAdapter implements RoleModel {
+
+    private final RoleData role;
+    private final NoSQL noSQL;
+
+    public RoleAdapter(RoleData roleData, NoSQL noSQL) {
+        this.role = roleData;
+        this.noSQL = noSQL;
+    }
+
+    @Override
+    public String getName() {
+        return role.getName();
+    }
+
+    @Override
+    public String getDescription() {
+        return role.getDescription();
+    }
+
+    @Override
+    public void setDescription(String description) {
+        role.setDescription(description);
+        noSQL.saveObject(role);
+    }
+
+    @Override
+    public String getId() {
+        return role.getId();
+    }
+
+    @Override
+    public void setName(String name) {
+        role.setName(name);
+        noSQL.saveObject(role);
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/models/nosql/adapters/UserAdapter.java b/services/src/main/java/org/keycloak/services/models/nosql/adapters/UserAdapter.java
new file mode 100644
index 0000000..781ba26
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/models/nosql/adapters/UserAdapter.java
@@ -0,0 +1,93 @@
+package org.keycloak.services.models.nosql.adapters;
+
+import java.util.Map;
+
+import org.keycloak.services.models.UserModel;
+import org.keycloak.services.models.nosql.api.NoSQL;
+import org.keycloak.services.models.nosql.data.UserData;
+
+/**
+ * Wrapper around UserData object, which will persist wrapped object after each set operation (compatibility with picketlink based impl)
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class UserAdapter implements UserModel {
+
+    private final UserData user;
+    private final NoSQL noSQL;
+
+    public UserAdapter(UserData userData, NoSQL noSQL) {
+        this.user = userData;
+        this.noSQL = noSQL;
+    }
+
+    @Override
+    public String getLoginName() {
+        return user.getLoginName();
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return user.isEnabled();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+       user.setEnabled(enabled);
+       noSQL.saveObject(user);
+    }
+
+    @Override
+    public String getFirstName() {
+        return user.getFirstName();
+    }
+
+    @Override
+    public void setFirstName(String firstName) {
+        user.setFirstName(firstName);
+        noSQL.saveObject(user);
+    }
+
+    @Override
+    public String getLastName() {
+        return user.getLastName();
+    }
+
+    @Override
+    public void setLastName(String lastName) {
+        user.setLastName(lastName);
+        noSQL.saveObject(user);
+    }
+
+    @Override
+    public String getEmail() {
+        return user.getEmail();
+    }
+
+    @Override
+    public void setEmail(String email) {
+        user.setEmail(email);
+        noSQL.saveObject(user);
+    }
+
+    @Override
+    public void setAttribute(String name, String value) {
+        user.setAttribute(name, value);
+    }
+
+    @Override
+    public void removeAttribute(String name) {
+        user.removeAttribute(name);
+        noSQL.saveObject(user);
+    }
+
+    @Override
+    public String getAttribute(String name) {
+        return user.getAttribute(name);
+    }
+
+    @Override
+    public Map<String, String> getAttributes() {
+        return user.getAttributes();
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/models/nosql/api/AbstractAttributedNoSQLObject.java b/services/src/main/java/org/keycloak/services/models/nosql/api/AbstractAttributedNoSQLObject.java
new file mode 100644
index 0000000..efdddee
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/models/nosql/api/AbstractAttributedNoSQLObject.java
@@ -0,0 +1,37 @@
+package org.keycloak.services.models.nosql.api;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public abstract class AbstractAttributedNoSQLObject implements AttributedNoSQLObject {
+
+    // Simple hashMap for now (no thread-safe)
+    private Map<String, String> attributes = new HashMap<String, String>();
+
+    @Override
+    public void setAttribute(String name, String value) {
+        attributes.put(name, value);
+    }
+
+    @Override
+    public void removeAttribute(String name) {
+        // attributes.remove(name);
+
+        // ensure that particular attribute has null value, so it will be deleted in DB. TODO: needs to be improved
+        attributes.put(name, null);
+    }
+
+    @Override
+    public String getAttribute(String name) {
+        return attributes.get(name);
+    }
+
+    @Override
+    public Map<String, String> getAttributes() {
+        return Collections.unmodifiableMap(attributes);
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/models/nosql/api/NoSQL.java b/services/src/main/java/org/keycloak/services/models/nosql/api/NoSQL.java
index dc16bb6..9da8166 100644
--- a/services/src/main/java/org/keycloak/services/models/nosql/api/NoSQL.java
+++ b/services/src/main/java/org/keycloak/services/models/nosql/api/NoSQL.java
@@ -15,12 +15,14 @@ public interface NoSQL {
 
     <T extends NoSQLObject> T loadObject(Class<T> type, String oid);
 
-    <T extends NoSQLObject> List<T> loadObjects(Class<T> type, Map<String, Object> queryAttributes);
+    <T extends NoSQLObject> T loadSingleObject(Class<T> type, NoSQLQuery query);
+
+    <T extends NoSQLObject> List<T> loadObjects(Class<T> type, NoSQLQuery query);
 
     // Object must have filled oid
     void removeObject(NoSQLObject object);
 
     void removeObject(Class<? extends NoSQLObject> type, String oid);
 
-    void removeObjects(Class<? extends NoSQLObject> type, Map<String, Object> queryAttributes);
+    void removeObjects(Class<? extends NoSQLObject> type, NoSQLQuery query);
 }
diff --git a/services/src/main/java/org/keycloak/services/models/nosql/api/NoSQLQuery.java b/services/src/main/java/org/keycloak/services/models/nosql/api/NoSQLQuery.java
new file mode 100644
index 0000000..d260644
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/models/nosql/api/NoSQLQuery.java
@@ -0,0 +1,34 @@
+package org.keycloak.services.models.nosql.api;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class NoSQLQuery {
+
+    private Map<String, Object> queryAttributes = new HashMap<String, Object>();
+
+    private NoSQLQuery() {};
+
+    public static NoSQLQuery create() {
+        return new NoSQLQuery();
+    }
+
+    public NoSQLQuery put(String name, Object value) {
+        queryAttributes.put(name, value);
+        return this;
+    }
+
+    public Map<String, Object> getQueryAttributes() {
+        return Collections.unmodifiableMap(queryAttributes);
+    }
+
+    @Override
+    public String toString() {
+        return "NoSQLQuery [" + queryAttributes + "]";
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/models/nosql/api/types/Converter.java b/services/src/main/java/org/keycloak/services/models/nosql/api/types/Converter.java
new file mode 100644
index 0000000..221db2b
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/models/nosql/api/types/Converter.java
@@ -0,0 +1,18 @@
+package org.keycloak.services.models.nosql.api.types;
+
+/**
+ * SPI object to convert object from application type to database type and vice versa. Shouldn't be directly used by application.
+ * Various converters should be registered in TypeConverter, which is main entry point to be used by application
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public interface Converter<T, S> {
+
+    T convertDBObjectToApplicationObject(S dbObject);
+
+    S convertApplicationObjectToDBObject(T applicationObject);
+
+    Class<? extends T> getApplicationObjectType();
+
+    Class<S> getDBObjectType();
+}
diff --git a/services/src/main/java/org/keycloak/services/models/nosql/api/types/ConverterKey.java b/services/src/main/java/org/keycloak/services/models/nosql/api/types/ConverterKey.java
new file mode 100644
index 0000000..f4b6fe0
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/models/nosql/api/types/ConverterKey.java
@@ -0,0 +1,30 @@
+package org.keycloak.services.models.nosql.api.types;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+class ConverterKey {
+
+    private final Class<?> applicationObjectType;
+    private final Class<?> dbObjectType;
+
+    public ConverterKey(Class<?> applicationObjectType, Class<?> dbObjectType) {
+        this.applicationObjectType = applicationObjectType;
+        this.dbObjectType = dbObjectType;
+    }
+
+    @Override
+    public int hashCode() {
+        return applicationObjectType.hashCode() * 13 + dbObjectType.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null || !obj.getClass().equals(this.getClass())) {
+            return false;
+        }
+
+        ConverterKey tc = (ConverterKey)obj;
+        return tc.applicationObjectType.equals(this.applicationObjectType) && tc.dbObjectType.equals(this.dbObjectType);
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/models/nosql/api/types/TypeConverter.java b/services/src/main/java/org/keycloak/services/models/nosql/api/types/TypeConverter.java
new file mode 100644
index 0000000..7bdb384
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/models/nosql/api/types/TypeConverter.java
@@ -0,0 +1,43 @@
+package org.keycloak.services.models.nosql.api.types;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Registry of converters, which allow to convert application object to database objects. TypeConverter is main entry point to be used by application.
+ * Application can create instance of TypeConverter and then register required Converter objects.
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class TypeConverter {
+
+    private Map<ConverterKey, Converter<?, ?>> converterRegistry = new HashMap<ConverterKey, Converter<?, ?>>();
+
+    public <T, S> void addConverter(Converter<T, S> converter) {
+        ConverterKey converterKey = new ConverterKey(converter.getApplicationObjectType(), converter.getDBObjectType());
+        converterRegistry.put(converterKey, converter);
+    }
+
+    public <T, S> T convertDBObjectToApplicationObject(S dbObject, Class<T> expectedApplicationObjectType, Class<S> expectedDBObjectType) {
+        Converter<T, S> converter = getConverter(expectedApplicationObjectType, expectedDBObjectType);
+        return converter.convertDBObjectToApplicationObject(dbObject);
+    }
+
+    public <T, S> S convertApplicationObjectToDBObject(T applicationobject, Class<T> expectedApplicationObjectType, Class<S> expectedDBObjectType) {
+        Converter<T, S> converter = getConverter(expectedApplicationObjectType, expectedDBObjectType);
+        return converter.convertApplicationObjectToDBObject(applicationobject);
+    }
+
+    private <T, S> Converter<T, S> getConverter( Class<T> expectedApplicationObjectType, Class<S> expectedDBObjectType) {
+        ConverterKey key = new ConverterKey(expectedApplicationObjectType, expectedDBObjectType);
+        Converter<T, S> converter = (Converter<T, S>)converterRegistry.get(key);
+
+        if (converter == null) {
+            throw new IllegalStateException("Can't found converter for expectedApplicationObject=" + expectedApplicationObjectType + ", expectedDBObjectType=" + expectedDBObjectType);
+        }
+
+        return converter;
+    }
+
+
+}
diff --git a/services/src/main/java/org/keycloak/services/models/nosql/data/RealmData.java b/services/src/main/java/org/keycloak/services/models/nosql/data/RealmData.java
new file mode 100644
index 0000000..8e6a663
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/models/nosql/data/RealmData.java
@@ -0,0 +1,144 @@
+package org.keycloak.services.models.nosql.data;
+
+import org.keycloak.services.models.nosql.api.NoSQLCollection;
+import org.keycloak.services.models.nosql.api.NoSQLField;
+import org.keycloak.services.models.nosql.api.NoSQLId;
+import org.keycloak.services.models.nosql.api.NoSQLObject;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+@NoSQLCollection(collectionName = "realms")
+public class RealmData implements NoSQLObject {
+
+    private String id;
+    private String name;
+    private boolean enabled;
+    private boolean sslNotRequired;
+    private boolean cookieLoginAllowed;
+    private boolean registrationAllowed;
+    private boolean social;
+    private boolean automaticRegistrationAfterSocialLogin;
+    private int tokenLifespan;
+    private int accessCodeLifespan;
+    private String publicKeyPem;
+    private String privateKeyPem;
+    private String[] defaultRoles;
+
+    @NoSQLId
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    @NoSQLField
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String realmName) {
+        this.name = realmName;
+    }
+
+    @NoSQLField
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    @NoSQLField
+    public boolean isSslNotRequired() {
+        return sslNotRequired;
+    }
+
+    public void setSslNotRequired(boolean sslNotRequired) {
+        this.sslNotRequired = sslNotRequired;
+    }
+
+    @NoSQLField
+    public boolean isCookieLoginAllowed() {
+        return cookieLoginAllowed;
+    }
+
+    public void setCookieLoginAllowed(boolean cookieLoginAllowed) {
+        this.cookieLoginAllowed = cookieLoginAllowed;
+    }
+
+    @NoSQLField
+    public boolean isRegistrationAllowed() {
+        return registrationAllowed;
+    }
+
+    public void setRegistrationAllowed(boolean registrationAllowed) {
+        this.registrationAllowed = registrationAllowed;
+    }
+
+    @NoSQLField
+    public boolean isSocial() {
+        return social;
+    }
+
+    public void setSocial(boolean social) {
+        this.social = social;
+    }
+
+    @NoSQLField
+    public boolean isAutomaticRegistrationAfterSocialLogin() {
+        return automaticRegistrationAfterSocialLogin;
+    }
+
+    public void setAutomaticRegistrationAfterSocialLogin(boolean automaticRegistrationAfterSocialLogin) {
+        this.automaticRegistrationAfterSocialLogin = automaticRegistrationAfterSocialLogin;
+    }
+
+    @NoSQLField
+    public int getTokenLifespan() {
+        return tokenLifespan;
+    }
+
+    public void setTokenLifespan(int tokenLifespan) {
+        this.tokenLifespan = tokenLifespan;
+    }
+
+    @NoSQLField
+    public int getAccessCodeLifespan() {
+        return accessCodeLifespan;
+    }
+
+    public void setAccessCodeLifespan(int accessCodeLifespan) {
+        this.accessCodeLifespan = accessCodeLifespan;
+    }
+
+    @NoSQLField
+    public String getPublicKeyPem() {
+        return publicKeyPem;
+    }
+
+    public void setPublicKeyPem(String publicKeyPem) {
+        this.publicKeyPem = publicKeyPem;
+    }
+
+    @NoSQLField
+    public String getPrivateKeyPem() {
+        return privateKeyPem;
+    }
+
+    public void setPrivateKeyPem(String privateKeyPem) {
+        this.privateKeyPem = privateKeyPem;
+    }
+
+    @NoSQLField
+    public String[] getDefaultRoles() {
+        return defaultRoles;
+    }
+
+    public void setDefaultRoles(String[] defaultRoles) {
+        this.defaultRoles = defaultRoles;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/models/nosql/data/RoleData.java b/services/src/main/java/org/keycloak/services/models/nosql/data/RoleData.java
new file mode 100644
index 0000000..7d4ba4b
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/models/nosql/data/RoleData.java
@@ -0,0 +1,65 @@
+package org.keycloak.services.models.nosql.data;
+
+import org.keycloak.services.models.nosql.api.NoSQLCollection;
+import org.keycloak.services.models.nosql.api.NoSQLField;
+import org.keycloak.services.models.nosql.api.NoSQLId;
+import org.keycloak.services.models.nosql.api.NoSQLObject;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+@NoSQLCollection(collectionName = "roles")
+public class RoleData implements NoSQLObject {
+
+    private String id;
+    private String name;
+    private String description;
+
+    private String realmId;
+    private String applicationId;
+
+    @NoSQLId
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    @NoSQLField
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @NoSQLField
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    @NoSQLField
+    public String getRealmId() {
+        return realmId;
+    }
+
+    public void setRealmId(String realmId) {
+        this.realmId = realmId;
+    }
+
+    @NoSQLField
+    public String getApplicationId() {
+        return applicationId;
+    }
+
+    public void setApplicationId(String applicationId) {
+        this.applicationId = applicationId;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/models/nosql/data/UserData.java b/services/src/main/java/org/keycloak/services/models/nosql/data/UserData.java
new file mode 100644
index 0000000..70aab2a
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/models/nosql/data/UserData.java
@@ -0,0 +1,85 @@
+package org.keycloak.services.models.nosql.data;
+
+import org.keycloak.services.models.nosql.api.AbstractAttributedNoSQLObject;
+import org.keycloak.services.models.nosql.api.NoSQLCollection;
+import org.keycloak.services.models.nosql.api.NoSQLField;
+import org.keycloak.services.models.nosql.api.NoSQLId;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+@NoSQLCollection(collectionName = "users")
+public class UserData extends AbstractAttributedNoSQLObject {
+
+    private String id;
+    private String loginName;
+    private String firstName;
+    private String lastName;
+    private String email;
+    private boolean enabled;
+
+    private String realmId;
+
+    @NoSQLId
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    @NoSQLField
+    public String getLoginName() {
+        return loginName;
+    }
+
+    public void setLoginName(String loginName) {
+        this.loginName = loginName;
+    }
+
+    @NoSQLField
+    public String getFirstName() {
+        return firstName;
+    }
+
+    public void setFirstName(String firstName) {
+        this.firstName = firstName;
+    }
+
+    @NoSQLField
+    public String getLastName() {
+        return lastName;
+    }
+
+    public void setLastName(String lastName) {
+        this.lastName = lastName;
+    }
+
+    @NoSQLField
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    @NoSQLField
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    @NoSQLField
+    public String getRealmId() {
+        return realmId;
+    }
+
+    public void setRealmId(String realmId) {
+        this.realmId = realmId;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/models/nosql/impl/MongoDBImpl.java b/services/src/main/java/org/keycloak/services/models/nosql/impl/MongoDBImpl.java
index bbdd846..7d61b85 100644
--- a/services/src/main/java/org/keycloak/services/models/nosql/impl/MongoDBImpl.java
+++ b/services/src/main/java/org/keycloak/services/models/nosql/impl/MongoDBImpl.java
@@ -13,6 +13,7 @@ import com.mongodb.DBCursor;
 import com.mongodb.DBObject;
 import org.bson.types.ObjectId;
 import org.jboss.resteasy.logging.Logger;
+import org.jboss.resteasy.spi.NotImplementedYetException;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.models.nosql.api.AttributedNoSQLObject;
 import org.keycloak.services.models.nosql.api.NoSQL;
@@ -20,9 +21,14 @@ import org.keycloak.services.models.nosql.api.NoSQLCollection;
 import org.keycloak.services.models.nosql.api.NoSQLField;
 import org.keycloak.services.models.nosql.api.NoSQLId;
 import org.keycloak.services.models.nosql.api.NoSQLObject;
+import org.keycloak.services.models.nosql.api.NoSQLQuery;
+import org.keycloak.services.models.nosql.api.types.Converter;
+import org.keycloak.services.models.nosql.api.types.TypeConverter;
+import org.keycloak.services.models.nosql.impl.types.BasicDBListToStringArrayConverter;
 import org.picketlink.common.properties.Property;
 import org.picketlink.common.properties.query.AnnotatedPropertyCriteria;
 import org.picketlink.common.properties.query.PropertyQueries;
+import org.picketlink.common.reflection.Types;
 
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -32,14 +38,20 @@ public class MongoDBImpl implements NoSQL {
     private final DB database;
     // private static final Logger logger = Logger.getLogger(MongoDBImpl.class);
 
+    private final TypeConverter typeConverter;
+
     public MongoDBImpl(DB database) {
         this.database = database;
+
+        typeConverter = new TypeConverter();
+        typeConverter.addConverter(new BasicDBListToStringArrayConverter());
     }
 
     private ConcurrentMap<Class<? extends NoSQLObject>, ObjectInfo<? extends NoSQLObject>> objectInfoCache =
             new ConcurrentHashMap<Class<? extends NoSQLObject>, ObjectInfo<? extends NoSQLObject>>();
 
 
+
     @Override
     public void saveObject(NoSQLObject object) {
         Class<?> clazz = object.getClass();
@@ -96,32 +108,62 @@ public class MongoDBImpl implements NoSQL {
     }
 
     @Override
-    public <T extends NoSQLObject> List<T> loadObjects(Class<T> type, Map<String, Object> queryAttributes) {
+    public <T extends NoSQLObject> T loadSingleObject(Class<T> type, NoSQLQuery query) {
+        List<T> result = loadObjects(type, query);
+        if (result.size() > 1) {
+            throw new IllegalStateException("There are " + result.size() + " results for type=" + type + ", query=" + query + ". We expect just one");
+        } else if (result.size() == 1) {
+            return result.get(0);
+        } else {
+            // 0 results
+            return null;
+        }
+    }
+
+    @Override
+    public <T extends NoSQLObject> List<T> loadObjects(Class<T> type, NoSQLQuery query) {
+        Map<String, Object> queryAttributes = query.getQueryAttributes();
+
         ObjectInfo<T> objectInfo = getObjectInfo(type);
         DBCollection dbCollection = database.getCollection(objectInfo.getDbCollectionName());
 
-        BasicDBObject query = new BasicDBObject();
+        BasicDBObject dbQuery = new BasicDBObject();
         for (Map.Entry<String, Object> queryAttr : queryAttributes.entrySet()) {
-            query.append(queryAttr.getKey(), queryAttr.getValue());
+            dbQuery.append(queryAttr.getKey(), queryAttr.getValue());
         }
-        DBCursor cursor = dbCollection.find(query);
+        DBCursor cursor = dbCollection.find(dbQuery);
 
         return convertCursor(type, cursor);
     }
 
     @Override
     public void removeObject(NoSQLObject object) {
-        //To change body of implemented methods use File | Settings | File Templates.
+        Class<? extends NoSQLObject> type = object.getClass();
+        ObjectInfo<?> objectInfo = getObjectInfo(type);
+
+        Property<String> idProperty = objectInfo.getOidProperty();
+        String oid = idProperty.getValue(object);
+
+        removeObject(type, oid);
     }
 
     @Override
     public void removeObject(Class<? extends NoSQLObject> type, String oid) {
-        //To change body of implemented methods use File | Settings | File Templates.
+        ObjectInfo<?> objectInfo = getObjectInfo(type);
+        DBCollection dbCollection = database.getCollection(objectInfo.getDbCollectionName());
+
+        BasicDBObject query = new BasicDBObject("_id", new ObjectId(oid));
+        dbCollection.remove(query);
     }
 
     @Override
-    public void removeObjects(Class<? extends NoSQLObject> type, Map<String, Object> queryAttributes) {
-        //To change body of implemented methods use File | Settings | File Templates.
+    public void removeObjects(Class<? extends NoSQLObject> type, NoSQLQuery query) {
+        throw new NotImplementedYetException();
+    }
+
+    // Possibility to add converters
+    public void addConverter(Converter<?, ?> converter) {
+        typeConverter.addConverter(converter);
     }
 
     private <T extends NoSQLObject> ObjectInfo<T> getObjectInfo(Class<?> objectClass) {
@@ -173,7 +215,20 @@ public class MongoDBImpl implements NoSQL {
 
             } else if ((property = objectInfo.getPropertyByName(key)) != null) {
                 // It's declared property with @DBField annotation
-                property.setValue(object, value);
+                Class<?> expectedType = property.getJavaClass();
+                Class actualType = value != null ? value.getClass() : expectedType;
+
+                // handle primitives
+                expectedType = Types.boxedClass(expectedType);
+                actualType = Types.boxedClass(actualType);
+
+                if (actualType.isAssignableFrom(expectedType)) {
+                    property.setValue(object, value);
+                } else {
+                    // we need to convert
+                    Object convertedValue = typeConverter.convertDBObjectToApplicationObject(value, expectedType, actualType);
+                    property.setValue(object, convertedValue);
+                }
 
             } else if (object instanceof AttributedNoSQLObject) {
                 // It's attributed object and property is not declared, so we will call setAttribute
diff --git a/services/src/main/java/org/keycloak/services/models/nosql/impl/types/BasicDBListToStringArrayConverter.java b/services/src/main/java/org/keycloak/services/models/nosql/impl/types/BasicDBListToStringArrayConverter.java
new file mode 100644
index 0000000..0f9d5d5
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/models/nosql/impl/types/BasicDBListToStringArrayConverter.java
@@ -0,0 +1,41 @@
+package org.keycloak.services.models.nosql.impl.types;
+
+import com.mongodb.BasicDBList;
+import org.keycloak.services.models.nosql.api.types.Converter;
+
+/**
+ * Convert BasicDBList to String[] and viceversa (T needs to be declared as Object as Array is not possible here :/ )
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class BasicDBListToStringArrayConverter implements Converter<Object, BasicDBList> {
+
+    private static final String[] PLACEHOLDER = new String[] {};
+
+    @Override
+    public Object convertDBObjectToApplicationObject(BasicDBList dbObject) {
+        return dbObject.toArray(PLACEHOLDER);
+    }
+
+    @Override
+    public BasicDBList convertApplicationObjectToDBObject(Object applicationObject) {
+        BasicDBList list = new BasicDBList();
+
+        String[] array = (String[])applicationObject;
+        for (String key : array) {
+            list.add(key);
+        }
+
+        return list;
+    }
+
+    @Override
+    public Class<?> getApplicationObjectType() {
+        return PLACEHOLDER.getClass();
+    }
+
+    @Override
+    public Class<BasicDBList> getDBObjectType() {
+        return BasicDBList.class;
+    }
+}
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 49855b9..089ab39 100755
--- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
+++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
@@ -7,6 +7,11 @@ import org.keycloak.models.picketlink.PicketlinkKeycloakSession;
 import org.keycloak.models.picketlink.PicketlinkKeycloakSessionFactory;
 import org.keycloak.models.picketlink.mappings.ApplicationEntity;
 import org.keycloak.models.picketlink.mappings.RealmEntity;
+import org.keycloak.services.models.KeycloakSessionFactory;
+import org.keycloak.services.models.nosql.adapters.MongoDBSessionFactory;
+import org.keycloak.services.models.picketlink.PicketlinkKeycloakSession;
+import org.keycloak.services.models.picketlink.mappings.ApplicationEntity;
+import org.keycloak.services.models.picketlink.mappings.RealmEntity;
 import org.keycloak.social.SocialRequestManager;
 import org.picketlink.idm.PartitionManager;
 import org.picketlink.idm.config.IdentityConfigurationBuilder;
@@ -54,8 +59,9 @@ public class KeycloakApplication extends Application {
     }
 
     public static KeycloakSessionFactory buildSessionFactory() {
-        EntityManagerFactory emf = Persistence.createEntityManagerFactory("keycloak-identity-store");
-        return new PicketlinkKeycloakSessionFactory(emf, buildPartitionManager());
+        // EntityManagerFactory emf = Persistence.createEntityManagerFactory("keycloak-identity-store");
+        // return new PicketlinkKeycloakSessionFactory(emf, buildPartitionManager());
+        return new MongoDBSessionFactory("localhost", 27017, "keycloak");
     }
 
     public KeycloakSessionFactory getFactory() {