Added MongoClientProvider. Possibility to configure mongo from external source
This commit is contained in:
parent
da3f1a21a2
commit
11bcd84738
7 changed files with 119 additions and 99 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue