Added MongoClientProvider. Possibility to configure mongo from external source

This commit is contained in:
mposolda 2014-03-07 13:39:43 +01:00
parent da3f1a21a2
commit 11bcd84738
7 changed files with 119 additions and 99 deletions

View file

@ -3,8 +3,8 @@ package org.keycloak.models.mongo.keycloak;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.ModelProvider;
import org.keycloak.models.mongo.keycloak.adapters.MongoKeycloakSessionFactory;
import org.keycloak.models.mongo.utils.MongoConfiguration;
import org.keycloak.models.mongo.utils.SystemPropertiesConfigurationProvider;
import org.keycloak.models.mongo.keycloak.config.MongoClientProvider;
import org.keycloak.models.mongo.keycloak.config.MongoClientProviderHolder;
import java.lang.Override;
@ -21,7 +21,7 @@ public class MongoModelProvider implements ModelProvider {
@Override
public KeycloakSessionFactory createFactory() {
MongoConfiguration config = SystemPropertiesConfigurationProvider.createConfiguration();
return new MongoKeycloakSessionFactory(config);
MongoClientProvider mongoClientProvider = MongoClientProviderHolder.getInstance();
return new MongoKeycloakSessionFactory(mongoClientProvider);
}
}

View file

@ -1,13 +1,12 @@
package org.keycloak.models.mongo.keycloak.adapters;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import org.jboss.logging.Logger;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.mongo.api.MongoEntity;
import org.keycloak.models.mongo.api.MongoStore;
import org.keycloak.models.mongo.impl.MongoStoreImpl;
import org.keycloak.models.mongo.keycloak.config.MongoClientProvider;
import org.keycloak.models.mongo.keycloak.entities.ApplicationEntity;
import org.keycloak.models.mongo.keycloak.entities.CredentialEntity;
import org.keycloak.models.mongo.keycloak.entities.OAuthClientEntity;
@ -16,9 +15,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.MongoConfiguration;
import java.net.UnknownHostException;
/**
* KeycloakSessionFactory implementation based on MongoDB
@ -39,22 +35,12 @@ public class MongoKeycloakSessionFactory implements KeycloakSessionFactory {
OAuthClientEntity.class
};
private final MongoClient mongoClient;
private final MongoClientProvider mongoClientProvider;
private final MongoStore mongoStore;
public MongoKeycloakSessionFactory(MongoConfiguration config) {
logger.info(String.format("Configuring MongoStore with: " + config));
try {
// TODO: authentication support
mongoClient = new MongoClient(config.getHost(), config.getPort());
DB db = mongoClient.getDB(config.getDbName());
mongoStore = new MongoStoreImpl(db, config.isClearCollectionsOnStartup(), MANAGED_ENTITY_TYPES);
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
public MongoKeycloakSessionFactory(MongoClientProvider provider) {
this.mongoClientProvider = provider;
this.mongoStore = new MongoStoreImpl(provider.getDB(), provider.clearCollectionsOnStartup(), MANAGED_ENTITY_TYPES);
}
@Override
@ -64,7 +50,6 @@ public class MongoKeycloakSessionFactory implements KeycloakSessionFactory {
@Override
public void close() {
logger.info("Closing MongoDB client");
mongoClient.close();
this.mongoClientProvider.close();
}
}

View file

@ -0,0 +1,21 @@
package org.keycloak.models.mongo.keycloak.config;
import com.mongodb.DB;
import com.mongodb.MongoClient;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface MongoClientProvider {
MongoClient getMongoClient();
DB getDB();
/**
* @return true if collections should be cleared on startup
*/
boolean clearCollectionsOnStartup();
void close();
}

View file

@ -0,0 +1,20 @@
package org.keycloak.models.mongo.keycloak.config;
/**
* Provides {@link MongoClientProvider} instance
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class MongoClientProviderHolder {
// Just use static object for now. Default impl is SystemPropsMongoClientProvider
private static MongoClientProvider instance = new SystemPropertiesMongoClientProvider();
public static MongoClientProvider getInstance() {
return instance;
}
public static void setInstance(MongoClientProvider instance) {
MongoClientProviderHolder.instance = instance;
}
}

View file

@ -1,9 +1,19 @@
package org.keycloak.models.mongo.utils;
package org.keycloak.models.mongo.keycloak.config;
import java.net.UnknownHostException;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import org.jboss.logging.Logger;
/**
* Instance of {@link MongoClientProvider} which reads configuration of MongoDB from system properties
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class SystemPropertiesConfigurationProvider {
public class SystemPropertiesMongoClientProvider implements MongoClientProvider {
protected static final Logger logger = Logger.getLogger(SystemPropertiesMongoClientProvider.class);
private static final String MONGO_HOST = "keycloak.mongo.host";
private static final String MONGO_PORT = "keycloak.mongo.port";
@ -14,11 +24,60 @@ public class SystemPropertiesConfigurationProvider {
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";
private static final String MONGO_CLEAR_ON_STARTUP_2 = "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 String MONGO_DEFAULT_PORT = "27017";
private MongoClient mongoClient;
private DB db;
@Override
public synchronized MongoClient getMongoClient() {
if (this.mongoClient == null) {
init();
}
return this.mongoClient;
}
@Override
public synchronized DB getDB() {
if (mongoClient == null) {
init();
}
return this.db;
}
@Override
public boolean clearCollectionsOnStartup() {
return isClearCollectionsOnStartup();
}
@Override
public synchronized void close() {
// Assume that client is dedicated just for Keycloak, so close it
logger.info("Closing MongoDB client");
mongoClient.close();
mongoClient = null;
db = null;
}
protected void init() {
try {
String host = getMongoHost();
int port = getMongoPort();
String dbName = getMongoDbName();
boolean clearOnStartup = isClearCollectionsOnStartup();
logger.info(String.format("Configuring MongoStore with: host=%s, port=%d, dbName=%s, clearOnStartup=%b", host, port, dbName, clearOnStartup));
this.mongoClient = new MongoClient(host, port);
this.db = mongoClient.getDB(dbName);
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
public static String getMongoHost() {
return getSystemPropertyWithFallback(MONGO_HOST, MONGO_HOST_2, "localhost");
}
@ -42,14 +101,4 @@ public class SystemPropertiesConfigurationProvider {
String propValue1 = System.getProperty(propName1);
return propValue1!=null ? propValue1 : System.getProperty(propName2, defaultValue);
}
// Create configuration based on system properties
public static MongoConfiguration createConfiguration() {
return new MongoConfiguration(
getMongoHost(),
getMongoPort(),
getMongoDbName(),
isClearCollectionsOnStartup()
);
}
}

View file

@ -1,44 +0,0 @@
package org.keycloak.models.mongo.utils;
/**
* Encapsulates all info about configuration of MongoDB instance
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class MongoConfiguration {
private final String host;
private final int port;
private final String dbName;
private final boolean clearCollectionsOnStartup;
public MongoConfiguration(String host, int port, String dbName, boolean clearCollectionsOnStartup) {
this.host = host;
this.port = port;
this.dbName = dbName;
this.clearCollectionsOnStartup = clearCollectionsOnStartup;
}
public String getHost() {
return host;
}
public int getPort() {
return port;
}
public String getDbName() {
return dbName;
}
public boolean isClearCollectionsOnStartup() {
return clearCollectionsOnStartup;
}
@Override
public String toString() {
return String.format("MongoConfiguration: host: %s, port: %d, dbName: %s, clearCollectionsOnStartup: %b",
host, port, dbName, clearCollectionsOnStartup);
}
}

View file

@ -1,8 +1,6 @@
package org.keycloak.models.mongo.test;
import com.mongodb.DB;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;
import com.mongodb.QueryBuilder;
import org.junit.After;
import org.junit.Assert;
@ -13,9 +11,8 @@ 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.TransactionMongoStoreInvocationContext;
import org.keycloak.models.mongo.utils.SystemPropertiesConfigurationProvider;
import java.net.UnknownHostException;
import org.keycloak.models.mongo.keycloak.config.MongoClientProvider;
import org.keycloak.models.mongo.keycloak.config.MongoClientProviderHolder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -31,26 +28,18 @@ public class MongoStoreTest {
AddressWithFlats.class
};
private MongoClient mongoClient;
private MongoClientProvider mongoClientProvider;
private MongoStore mongoStore;
@Before
public void before() throws Exception {
try {
// TODO: authentication support
mongoClient = new MongoClient("localhost", SystemPropertiesConfigurationProvider.getMongoPort());
DB db = mongoClient.getDB("keycloakTest");
mongoStore = new MongoStoreImpl(db, true, MANAGED_DATA_TYPES);
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
mongoClientProvider = MongoClientProviderHolder.getInstance();
mongoStore = new MongoStoreImpl(mongoClientProvider.getDB(), true, MANAGED_DATA_TYPES);
}
@After
public void after() throws Exception {
mongoClient.close();
mongoClientProvider.close();
}
@Test